I have a code that is supposed to generate a curve for regulation purposes which works fine.
Coming from a Linux environment, I did not really know how to code on Windows (which I have to use at work) so I just went on and downloaded Code::Blocks with MinGW.
Now the problem is the following : My code works, but sometimes it crashes. I tried it on Linux and I don't have any problem running it, on Windows however, sometimes it will work, sometimes it won't and tell me this.
Problem signature:
Problem Event Name: APPCRASH
Application Name: TabGen.exe
Application Version: 0.0.0.0
Application Timestamp: 02881c68
Fault Module Name: ntdll.dll
Fault Module Version: 6.1.7601.23418
Fault Module Timestamp: 5708a73e
Exception Code: c0000005
Exception Offset: 00032a62
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 2055
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
To be fairly honest, I don't really understand. I tried looking up "Exception code c0000005 windows" which apparently means "access violation", but I do not understand where it comes from because as stated it sometimes works sometimes it doesn't.
Is it MinGW related ? Have I done something wrong in my code ? I have a function mk_cp_table (which always uses 4096 values, that's why it is not a function parameter) but I'm pretty positive it is alright.
Also if you are wondering why I'm using calloc instead of an array, it's again because of an error I don't understand. The fprintf at the end in the last function did not work if I had my values in an array (however displaying them with printf alone worked perfectly, but fprintf only left blank files whenever I would run it).
Any ideas ?
My code :
#include <stdio.h>
#include <stdlib.h>
void tab2file(FILE*, int, int*);
void mk_cp_table (int*, float, float, float, int, float, float, int);
int main (void)
{
FILE* cp_file = fopen("cp_table.txt", "w");
if (cp_file == NULL)
{
perror("failed fopen for cp_file\n");
exit(EXIT_FAILURE);
}
int* cp_table = calloc((size_t) 4096, sizeof (int));
if (cp_table == NULL)
{
fclose(cp_file);
perror("failed calloc for cp_table\n");
exit(EXIT_FAILURE);
}
/* Generate curves */
mk_cp_table(
cp_table,
0.142, /* scale */
20, /* zeroed distance 0 (negative part) */
0.04, /* slope 0 */
120, /* range 0 */
20, /* zeroed distance 1 (positive part) */
0.04, /* slope 1 */
120 /* range 1 */
);
printf("\ntable generated\n");
tab2file(cp_file, 4096, cp_table);
printf("\ntables written to files\n");
fclose(cp_file);
free(cp_table);
return EXIT_SUCCESS;
}
void tab2file(FILE* file, int size, int* table)
{
int i;
for (i = 0; i < size; i++)
fprintf(file, "%d\n", table[i]);
}
void mk_cp_table(int* table, float scale, float zeroes_0, float slope_0, int range_0, float zeroes_1, float slope_1, int range_1)
{
int i;
int value;
zeroes_0 = zeroes_0 / scale;
zeroes_1 = zeroes_1 / scale;
for (i = 0; i < 2048; i++)
{
if (i < zeroes_1)
value = 0;
else
value = (i - zeroes_1) * slope_1;
if (value > range_1)
value = 127;
table[i] = 0;
}
for (i = 0; i < 2048; i++)
{
if (i < zeroes_0)
value = 0;
else
value = (zeroes_0 - i) * slope_0;
if (value < -range_0)
value = -127;
table[4096 - i] = value;
}
}
For an array of 4096 elements, 4095 is the largest valid index you can use. The statement table[4096 - i] = value; writes to table[4096] when i==0, which is outside the bounds of table.
Presumably you meant to do table[4095 - i] = value;, which will give you an index of 4095..2048.
For completeness, so this question doesn't remain in the unanswered section, you are writing out of bounds on the last line of your program in the for loop:
for (i = 0; i < 2048; i++)
{
if (i < zeroes_0)
value = 0;
else
value = (zeroes_0 - i) * slope_0;
if (value < -range_0)
value = -127;
table[4096 - i] = value; // out of bounds when i = 0.
}
This is causing the windows equivalent of a seg fault aka access violation. You would notice this on unix too if you ran it under valgrind.
As it turned out it was a segmentation fault, I had table[4096 - i] = value; which would be out of the array's bounds when i was equal to 0.
Sometimes when you focus too much on a part of the code you thought was not working you forget to check the part you thought was working.
Related
I was writing a program that is reading from a file and then storing the data in two tables that are in a table of structure. I am expanding the tables with realloc and the time my program takes to run is ~ 0.7 s.
Can i somehow decrease this time?
typedef struct {
int *node;
int l;
int *waga;
} przejscie_t;
void czytaj(przejscie_t **graf, int vp, int vk, int waga) {
(*graf)[vp].node[(*graf)[vp].l - 1] = vk;
(*graf)[vp].waga[(*graf)[vp].l - 1] = waga;
(*graf)[vp].l++;
}
void wypisz(przejscie_t *graf, int i) {
printf("i=%d l=%d ", i, graf[i].l);
for (int j = 0; j < (graf[i].l - 1); j++) {
printf("vk=%d waga=%d ", graf[i].node[j], graf[i].waga[j]);
}
printf("\n");
}
void init(przejscie_t **graf, int vp, int n) {
*graf = realloc(*graf, (vp + 1) * sizeof(przejscie_t));
if (n == vp || n == -1){
(*graf)[vp].l = 1;
(*graf)[vp].node = malloc((*graf)[vp].l * sizeof(int));
(*graf)[vp].waga = malloc((*graf)[vp].l * sizeof(int));
}
else {
for (int i = n; i <= vp; i++) {
(*graf)[i].l = 1;
(*graf)[i].node = malloc((*graf)[i].l * sizeof(int));
(*graf)[i].waga = malloc((*graf)[i].l * sizeof(int));
}
}
}
Here some suggestions:
I think you should pre-calculate the required size of your *graf memory instead of reallocating it again and again. By using a prealloc_graf function for example.
You will get some great time improvement since reallocating is time-consuming especially when it must actually move the memory.
You should do this method especially if you are working with big files.
And since you're working with files, pre-calculating should be done easily.
If your files size are both light and heavy, you have two choices:
Accept your fate and allow your code to be a little bit less optimized on small files.
Create two init functions: The first one is optimized for small files, the other one will be for bigger files but... You will have to run some benchmarks to actually determine what algorithm is the best for each case before being able to implement it. You could actually automate that if you have the time and the will to do so.
It is important to check for successful memory allocation before trying to use the said memory because allocation function can fail.
Finally, some changes for the init function :
void init(przejscie_t **graf, int vp, int n) {
*graf = realloc(*graf, (vp + 1) * sizeof(przejscie_t));
// The `if` statement was redundant.
// Added a ternary operator for ``n == -1``.
// Alternatively, you could use ``n = (n == -1 ? vp : n)`` right before the loop.
for (int i = (n == -1 ? vp : n); i <= vp; i++) {
(*graf)[i].l = 1;
// (*graf)[X].l is is always 1.
// There is no reason to use (*graf)[X].l * sizeof(int) for malloc.
(*graf)[i].node = malloc(sizeof(int));
(*graf)[i].waga = malloc(sizeof(int));
}
}
I've commented everything that I've changed but here is a summary :
The if statement was redundant.
The for loop cover all cases with ternary operator for n
equals -1.
The code should be easier to understand and to comprehend this way.
The node and waga arrays were not being initialized "properly".
Since l is always equals 1 there was no need for an
additional operation.
This doesn't really change execution time tho since its constant.
I would also suggest that your "functions running allocation functions" should return a boolean saying if the function succeeded. In the case the allocation failed you can return false to say that your function failed.
#include <stdio.h>
#define LENGTH_OF_A_MACRO 3
struct blahS
{
unsigned int groupsToTrace[LENGTH_OF_A_MACRO];
} blahS;
int main()
{
//Value hardcoded to 7 just for testing purpose. Otherwise value is assigned from another function
signed int trace = 7; //trace reads value of range [0-7] from a function
unsigned int ToTrace[LENGTH_OF_A_MACRO];
unsigned int number = 0;
unsigned int noOfGroups = 100;
if (trace != 0)
{
if ((trace == 1)) //b'001
{
ToTrace[number] = noOfGroups / 8;
number++;
}
if ((trace == 4)) //b'100
{
ToTrace[number] = noOfGroups / 2;
number++;
}
if ((trace == 7)) //b'111
{
ToTrace[number] = noOfGroups * 7 / 8;
number++;
}
}
struct blahS blah;
blah.groupsToTrace[LENGTH_OF_A_MACRO] = ToTrace[number]; //Compilation-error
return 0;
}
Basically this is an if-loop which checks and decides groupToTrace based on bit-mapping for a trace value allocated. At the last line i got a compilation error saying - Array index 3 is past the end of the array. I am assigning the calculated groupToTrace values to newPointer_p->groupsToTrace[3] where groupsToTrace[3] is stored in a struct
Question is I got a compilation error as mentioned above with out of bounds access to the array as i understand. But i don't understand where is the mistake.
Compiler version gcc.x86_64 4.8.5-39.el7 #GSS-RHEL7
Any clues or hints highly appreciated. Thanks in Advance!
You seem to misunderstand what this line is doing:
blah.groupsToTrace[LENGTH_OF_A_MACRO] = ToTrace[number];
This is not copying the entire contents of one array to another. It is copying index number of ToTrace to index LENGTH_OF_A_MACRO of blah.groupsToTrace. Both of these indices have the value 3 which is out of bounds for both arrays, as an array of size 3 has indices 0, 1, and 2.
You either need a loop to copy the elements:
int i;
for (i=0; i<number; i++) {
blah.groupsToTrace[i] = ToTrace[i];
}
Or you could use memcpy:
memcpy(blah.groupsToTrace, ToTrace, sizeof(blah.groupsToTrace));
Visual Studio 2019 started showing Code Analysis warnings as in-editor green squiggles by default. These may be extremely useful for students learning C programming, because they catch classical mistakes, such as off by one array accesses.
Unfortunately false positives may completely ruin the learning experience and I fear that I will have to ask the students to disable the feature in order to avoid having them worry on non existing problems.
This short snippet doesn't cause any warning:
#include <stdlib.h>
int main(void)
{
size_t n = 6;
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return 1;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
free(v);
return 0;
}
Unfortunately, if you move the allocation in a function, like this:
#include <stdlib.h>
int *test(size_t n)
{
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
int main(void)
{
size_t n = 6;
int *v = test(n);
free(v);
return 0;
}
you get a warning C6386: Buffer overrun while writing to 'v': the writable size is 'n*sizeof(int)' bytes, but '8' bytes might be written.
Even reading on Stack Overflow, I don't get where the '8' comes from, but, more importantly, why it fails to recognize that i will never be out of range.
So the question is: is there a way to write this type of code in a way that will not generate the warning?
I know that I can go to Tools > Options > Text Editor > C/C++ > Experimental > Code Analysis and set Disable Code Analysis Squiggles to True, or use a #pragma warning(disable:6386), but I'd rather avoid it, and certainly avoid suggesting my students the latter.
I really want to thank everybody for their contributions and I agree that it is a bug in the Code Analyzer (by looking on Microsoft web sites it has been "Closed - Lower Priority" two years ago...).
Adrian Mole max(n, 0) trick points to a way for coping with the warning in code, that is checking that n is greater than zero. The funny thing is that you can still use that zero for what n was supposed to be used. While the idea could be used for experienced programmers (that would probably disable the warning), as John Bollinger points out, it's not for students.
So, after telling the students that it's a bug and how to turn off the Code Analysis squiggles or disable the warning, I'd go with
int *test(size_t n)
{
if (n == 0) {
return NULL;
}
int *v = malloc(n * sizeof(int));
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
Which may also be interpreted as: don't allow 0 elements allocation.
You can supress this warning (which could be considered a bug), simply by ensuring the value of n given to the malloc call has not "wrapped around" following overflow (as hinted at in the comment from Eric Postpischill).
To do this, you can replace the n argument by the seemingly bizarre max(n,0):
int* test(size_t n)
{
// int* v = malloc(n * sizeof(int)); // Warning C6386 on v[i] = i
int* v = malloc(max(n, 0) * sizeof(int)); // No warning
if (v == NULL) {
return NULL;
}
for (size_t i = 0; i < n; ++i) {
v[i] = i;
}
return v;
}
I need help with figuring out what exactly is this error and why is it occuring. When I debud the program everything seems to be working perfectly fine! I do not get this.
Code:
void WordsRandom()
{
srand((unsigned)time(NULL));
n = rand() % 10;
checkRandom[k] = n; //ERROR HERE --> THREAD 1: EXC_BAD_ACCESS
k ++; //k is set to 0 originally
rowRandom = getRandomNumber();
colRandom = getRandomNumber();
}
I do not know why this is happening. As far as I know, in this case there is no need to use the %d specifier right? I f you require further code just let me know.
WordsRandom is being called by other methods:
void horizontalOrientation()
{
size = (int)strlen(words[n]);
if((colRandom + (size - 1)) <= 9)
{
for(int j = 0; j < (strlen(words[n])); j ++)
{
puzzle[rowRandom][colRandom] = words[n][j];
colRandom ++;
}
}
else
{
do
{
WordsRandom();
horizontalOrientation();
}while((colRandom + (size - 1)) > 9);
}
}
I have other functions similiar to this for vertical and diagonal orientation.
Two things are troublesome here:
I do not see declarations for either the size of your array (checkRandom[]) or the integer value that you're using to index it (k). If you're receiving an access error, then chances are that you're indexing past the boundaries of your array into memory that isn't yours.
I'd try refactoring your code so that you can check you aren't passing the maximum index of your array (size -1)
I have traced an EXC_BAD_ACCESS to the following allocation and deallocation of memory. It involves the accelerate framework in Xcode. The main issue is that this code is in a loop. If i force the loop to only iterate once then it works fine. But when it loops (7 times) it causes an error on the second iteration. Does any of this look incorrect?
EDIT: *added actual code. This segment runs if I remove certain parts and such but seems to have poor memory management which results in issues
#import <Foundation/Foundation.h>
#include <math.h>
#include <Accelerate/Accelerate.h>
for(int i = 0; i < 8; i++)
{
int XX[M][m]; //M and m are just 2 ints
for(int kk = 0; kk < M; kk++)
{
for (int kk1 = 0; kk1 < m; kk1++)
{
XX[kk][kk1] = [[x objectAtIndex: (kk + kk1 * J)] intValue]; //x is a NSMutableArray of NSNumber objects
}
}
double FreqRes = (double) freqSamp/n;
NSMutableArray *freqs = [[NSMutableArray alloc] initWithCapacity: round((freqSamp/2 - FreqRes) - 1)];
int freqSum = 0;
for(double i = -1 * freqSamp/2; i < (freqSamp/2 - FreqRes); i+= FreqRes)
{
[freqs addObject: [NSNumber numberWithInt: i]];
if(i == 0)
{
freqSum++;
}
}
int num = [x count];
int log2n = (int) log2f(num);
int nOver2 = n / 2;
FFTSetupD fftSetup = vDSP_create_fftsetupD (log2n, kFFTRadix2);
double ffx[num];
DSPDoubleSplitComplex fft_data;
fft_data.realp = malloc(nOver2 * sizeof(double)); //Error usually thrown on this line in the second iteration. Regardless of what I put there. If I add an NSLog here it throws the error on that NSLog
fft_data.imagp = malloc(nOver2 * sizeof(double));
for (int i = 0; i < n; ++i)
{
ffx[i] = [[x objectAtIndex:i] doubleValue];
}
vDSP_ctozD((DSPDoubleComplex *) ffx, 2, &fft_data, 1, nOver2);
vDSP_fft_zripD (fftSetup, &fft_data, 1, log2n, kFFTDirection_Forward);
for (int i = 0; i < nOver2; ++i)
{
fft_data.realp[i] *= 0.5;
fft_data.imagp[i] *= 0.5;
}
int temp = 1;
ffx[0] = abs(fft_data.realp[0]);
for(int i = 1; i < nOver2; i++)
ffx[i] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
ffx[nOver2] = abs(fft_data.imagp[0]);
for(int i = nOver2-1; i > 0; i--)
{
ffx[nOver2 + temp] = sqrt((fft_data.realp[i] * fft_data.realp[i]) + (fft_data.imagp[i] * fft_data.imagp[i]));
temp++;
}
//clear Fxx and freqs data
vDSP_destroy_fftsetupD(fftSetup);
free(fft_data.imagp);
free(fft_data.realp);
[freqs release];
}
Your problem could be that you are casting malloc to a value. As you're tagging this c, I'm assuming that you are compiling in c in which case you should see this answer to a previous question as to why casting with malloc is bad:
https://stackoverflow.com/a/1565552/1515720
you can get an unpredictable runtime error when using the cast without including stdlib.h.
So the error on your side is not the cast, but forgetting to include stdlib.h. Compilers may assume that malloc is a function returning int, therefore converting the void* pointer actually returned by malloc to int and then to your your pointer type due to the explicit cast. On some platforms, int and pointers may take up different numbers of bytes, so the type conversions may lead to data corruption.
Regardless though, as the answer says, YOU SHOULD NOT BE CASTING MALLOC RETURNS, because void*'s are safely implicitly converted to whatever you are assigning it to.
As another answerer stated:
vDSP_destroy_fftsetupD(fftSetup);
Could be also free'ing the memory you allocated on accident.
Any chance the destructor of DSPDoubleSplitComplex is freeing up those two allocated blocks?
It could also be that you are only allowed to call vDSP_create_fftsetupD and vDSP_destroy_fftsetupD once during your process's lifetime