C Array Behaviour - Global / Local / Dynamic - c

I am having problems updating an array globally from a while loop, as expalined below. Please note that I can only use functionality from C 95 and before. Anyhelp would be greatly appreciated! Full paste bin http://pastebin.com/ss6VgTCD
Declared at the Top of my program
int data_count, i;
float *x_values, *y_values;
float x[100],y[100];
In My main function my arrays are created using the code below:
printf("\nPlease Enter How Many Data Points You Wish To Enter: \n");
scanf("%d", &data_count);
x_values=(float*)calloc(data_count,sizeof(*x_values));
y_values=(float*)calloc(data_count,sizeof(*y_values));
if (x_values==NULL) {
printf("Error! Memory Could Not Be Allocated. ");
exit(0);
}
File read function to import previously entered data, the function is getting the correct data and displays the correct data points in my debugging line printf("%12f%12f\n", x_values[i], y_values[i]); however is only locally updating x_values and y_values as these imported data can not be seen by the rest of the program. How can I globally update the array?
void file_read(void) {
store = fopen ("j:/StoredValues.txt", "r");
if (store == NULL )
printf("\nError: Failed To Open Previous Data File - Program Will Continue Anyway\n");
else {
printf("\nSuccess: Data From Previous Run Imported\n");
i=0;
do {
fscanf ( store, "%f,%f\n", &x[i], &y[i]);
x_values = x;
y_values = y;
printf("%12f%12f\n", x_values[i], y_values[i]);
i=i+1;
} while (!feof(store));
fclose(store);
}
}
p.s. Ive only coded in C for 2 weeks so simple is nice :)

In the first code block you've allocated memory and saved the pointer to it in 'x_values'.
In the second block you change 'x_values' to point to the 'x' array. The 'x' array already has memory allocated to it for 100 floating point values.
You will no longer have a pointer to the allocated memory after the assignment.
Any data stored there is no longer accessible since you no longer have a pointer to it.
edit:
Here's a suggested replacement for the file_read() routine:
void file_read(void) {
store = fopen ("j:/StoredValues.txt", "r");
if (store == NULL )
printf("\nError: Failed To Open Previous Data File - Program Will Continue Anyway\n");
else {
printf("\nSuccess: Data From Previous Run Imported\n");
float* px;
float* py;
px = x_values;
py = y_values;
while (!feof(store))
{
fscanf ( store, "%f,%f\n", px, py);
printf("%12f%12f\n", *px, *py );
px++;
py++;
}
fclose(store);
}
}
Edit 2:
Menu choice 2 will display the content of x_values. If file_read() places the content in the x array then you can't display it using option 2. You also can't copy the content of the x array to x_values since x_values doesn't exist yet.
You need to create a storage area for your data before you try to read it in.
To do that you need to store the count of how many points are in the file.
Also consider:
The user enters 10 points and you allocate space for 10.
Then the user wants to enter new data and wants to enter 12.
You now have to free() and alloc() to get space for the extra two.

x_values = x;
y_values = y;
This causes x_values and y_values to point at the statically allocated arrays instead of the data you allocated dynamically for them. So after this assignment, the dynamic data now sits alone and isolated in your RAM as a memory leak, with no reference to it from your program.

Related

C: Realloc() after reading second line in file results in garbage values

I'm attempting to read sequences from a FASTA file into a table of structs that I've created, which each contain a character array member called "seq". My code seems to work well for the first loop, but when I realloc() memory for the second sequence, the pointer seems to point to garbage values and then the strcat() method gives me a segfault.
Here's the whole FASTA file I'm trying to read from:
>1
AAAAAAAAAAGWTSGTAAAAAAAAAAA
>2
LLLLLLLLLLGWTSGTLLLLLLLLLLL
>3
CCCCCCCCCCGWTSGTCCCCCCCCCCC
Here's the code (sorry that some of the variable names are in french):
typedef struct _tgSeq { char *titre ; char *seq ; int lg ; } tgSeq ;
#define MAX_SEQ_LN 1000
tgSeq* readFasta(char *nomFile) {
char ligne[MAX_SEQ_LN];
tgSeq *lesSeq = NULL;
int nbSeq=-1;
FILE *pF = fopen(nomFile, "r");
while(fgets(ligne, MAX_SEQ_LN, pF) != NULL) {
if(ligne[0] == '>') {
/*create a new sequence*/
nbSeq++;
//reallocate memory to keep the new sequence in the *lesSeq table
lesSeq = realloc(lesSeq, (nbSeq)*sizeof(tgSeq));
//allocate memory for the title of the new sequence
lesSeq[nbSeq].titre = malloc((strlen(ligne)+1)*sizeof(char));
//lesSeq[nbSeq+1].titre becomes a pointer that points to the same memory as ligne
strcpy(lesSeq[nbSeq].titre, ligne);
//Now we create the new members of the sequence that we can fill with the correct information later
lesSeq[nbSeq].lg = 0;
lesSeq[nbSeq].seq = NULL;
} else {
/*fill the members of the sequence*/
//reallocate memory for the new sequence
lesSeq[nbSeq].seq = realloc(lesSeq[nbSeq].seq, (sizeof(char)*(lesSeq[nbSeq].lg+1+strlen(ligne))));
strcat(lesSeq[nbSeq].seq, ligne);
lesSeq[nbSeq].lg += strlen(ligne);
}
}
// Close the file
fclose(pF);
return lesSeq;
}
For the first line (AAAAAAAAAAGWTSGTAAAAAAAAAAA), lesSeq[nbSeq].seq = realloc(lesSeq[nbSeq].seq, (sizeof(char)*(lesSeq[nbSeq].lg+1+strlen(ligne)))); gives me an empty character array that I can concatenate onto, but for the second line (LLLLLLLLLLGWTSGTLLLLLLLLLLL) the same code gives me garbage characters like "(???". I'm assuming the problem is that the reallocation is pointing towards some sort of garbage memory, but I don't understand why it would be different for the first line versus the second line.
Any help you could provide would be greatly appreciated! Thank you!
The problem here is the first realloc gets the value of nbSeq as 0 which does not allocate any memory.
Replace
int nbSeq=-1;
with
int nbSeq=0;
Access the index with lesSeq[nbSeq - 1]
Some programmer dude already pointed out that you do not allocate enough memory.
You also seem to expect some behaviour from realloc that will not happen.
You call realloc with NULL pointers. This will make it behave same as malloc.
For the first line (AAAAAAAAAAGWTSGTAAAAAAAAAAA), ...= realloc(); gives me an empty character array that I can concatenate onto, but for the second line (LLLLLLLLLLGWTSGTLLLLLLLLLLL) the same code gives me garbage characters like "(???".
You should not expect any specifiy content of your allocated memory. Especially the memory location is not set to 0. If you want to rely on that, you can use calloc.
Or you simply assign a 0 to the first memory location.
You do not really concatenaty anything. Instead you allocate new memory where you could simply use strcpy instead of strcat.

The last value of an array of array of ints overrides all other values

I'm trying to store 4 arrays in an array, and for some reason, the last value keeps overriding the previous three values. For example, if 123; 456; 789; 987 were inputted into the code below, ipadr[0] - ipadr[4] would all only store 123. I've tested to make sure that numConvert() is working, and within numConvert, 4 different arrays of ints are returned, but only numConvert(d) is the ipadr array (stored 4 times).
Also, is my syntax / code correct in order for this function to return ipadr as an array of arrays (int**)? Why do you need to make it static int* when initializing the array?
I'm new to C and this has been really frustrating me. Any help would be incredibly appreciated. Thank you in advance!!
int** ipConvert(int a, int b, int c, int d){
static int* ipadr[4];
ipadr[0]=numConvert(a);
ipadr[1]=numConvert(b);
ipadr[2]=numConvert(c);
ipadr[3]=numConvert(d);
return ipadr;
}
numConvert code:
int* numConvert(int dec) {
static int hold[8];
...
return hold;
}
The hold array is indeed overwritten after each call to numConvert, because it is a static area of 8 int.
Better use dynamic allocation with malloc, and have that function allocate 8 ints.
int* numConvert(int dec) {
int *hold = (int *)malloc(sizeof(int) * 8); // C++ need cast!
int x = dec;
for(int y=7;y>=0;y--){
if(x%2==0 || x==0){
hold[y]=0;
}
else{
hold[y]=1;
}
x=x/2;
}
printf("\ntest loop: ");
for(int i=0;i<8;i++){
printf("%i", hold[i]);
}
printf("\n");
return hold;
}
then the returned values will have to be freed, after you don't need them anymore.
As for static, this answer explains it in details.
Every time you write something in hold then return it, you basically overwrite the previous value. There is single instance of hold not multiple as you may be thinking.
static keyword you have used without knowing the full functionality. It is not the same as automatic storage duration.
int* numConvert(int dec) {
int *hold = malloc(sizeof *hold *8);
if( hold == NULL){
fprintf(stderr,"Error in malloc");
exit(1);
}
int x = dec;
....
....
return hold;
}
Free the dynamically allocated memory when you are done working with it.
What have we done here?
Dynamically allocated memory has lifetime beyond the scope of the function. So just like the static one it stays alive. But with contrary to the static variable each time a new chunk of memory is allocated. And for that we are not overwriting anything, which was the primary problem in your case.
One thing more..
hold is of automatic storage duration meaning every time we exit the function the hold is deallocated and then again when we call it we get to have a local variable named hold. So in each we get different instance. And that's why we return the address contained in hold. This memory whose address hold contains has lifetime beyond the scope of the function. So it stays unlike the local variable hold and we store this address in other function.
Declare your hold variable as instance variable rather then static variable like
int* numConvert(int dec) {
int hold[8];

Segfault during calculation loop

I wrote a collection of codes to solve some physical problems. Unfortunately I cannot show the whole of the codes (they are too long and belong to a private project), but roughly, structure of my program is
double **array1; // declared globally
double **array2; // because there are a lot of functions using array1 & 2
main{
double x;
fscanf(input); // reading an input file
fclose(input); // input file have information about dimension of array
// and step to do different calculation
array = *calloc(~);
array[i] = calloc(~); // making 2d array with dimension from input file
for(i=0;i<large number;i++){
// (doing physical calculation using array1 and array2);
if(i==some step from input file){
// (calculation using array2)
x = array1[k][0]-array1[l][0] ... // !!SEGFAULT!!
}
}
The problem is that regardless of the dimensions of array or any other variables included in the input file, when the program approaches !!SEGFAULT!! region, it produces segmentation fault (using gdb...). "Some step" can be 1, 10, 100, ..., and I tried several tests varying the contents of input files but the program produces segfault only at that region. Valgrind says there is no memory leakage.
One thing strange is that at the beginning of the program, gdb says the address of array1 is (double **) 0x68e410, and this does not change until the program reaches the problematic point. At that point the address of array1 changes to (double **) 0x3ff223bf06cdec4d and I cannot access any of elements of array1.
If I set "some step" to be very large I may avoid the segfault problem but this is not the solution and contaminates the calculation procedure of our project... What is the origin of this problem?
Given the scant information...
these two lines are the root of the problem.
array = *calloc(~);
array[i] = calloc(~);
Using a concrete example:
int **array = NULL;
// notice, in following line that the second parameter to calloc()
// is the size of a pointer
array = calloc( 100, sizeof(int*) );
// each entry in the array[]
// must be set to point to some (more) allocated memory
for( int i=0; i<100; i++ )
{
array[i] = calloc( 20, sizeof( int ) );
}
Of course, each call to calloc() must be followed by a check to assure the returned value is not NULL.

C - Getting a Debug Assertion Failed Error by reading a csv-file

i am just doing a program in C, which has to read different files in csv-format. Every file consists of two lines.
The first line describes what topics are saved, while the second lines contains the data of the topics. Every file has
6 columns. The data are information like dates, source and category. I actually wrote a program that get the path and
gives the content in one dynamical char array back, but there is always a Debug Assertion Error that crashes it all the time. My Code is:
char* readfile(char csvpath[]) {
FILE *csv;
int c;
int countcontent = 100; //counter for the length of the content array
int counter = 0; //counter of the amount of the inserted chars
char *temp; //temp = buffer
char *content = (char*)calloc(100,sizeof(char)); //content of the file
csv = fopen(csvpath,"r");
while(c = fgetc(csv) != EOF) { //while file isnt at the end
if(countcontent <= counter) {
realloc(content,100*sizeof(char));
countcontent += 100;
}
temp = (char*)calloc(20,sizeof(char));
fgets(temp,20,csv);
content = concat(content,temp); //concat is my own function and add the 2. string behind the 1.
counter+= 20;
}
fclose(csv);
return content;}
Actually i ignore that there are two different lines, cause i want to delete the first one at the end anyway, because no data is saved there. But can you help me to find the solution for this error?
Your problem is this line
realloc(content,100*sizeof(char));
The realloc function returns a pointer to the reallocated memory. Think about what would happen if the realloc call can't just resize the already allocated chunk, and has to actually allocate a completely new chunk of memory, because it can't automatically update the pointer you pass to it.
Another problem with that statement is that it doesn't matter how much more memory you need, you will always allocate 100 bytes. The size argument you provide to realloc is the new size.
Oh, and remember that realloc can fail, and return a NULL pointer. If you don't want to loose your original pointer, you need to have a temporary variable to store the returned pointer, and check it for NULL.

c free pointer to structure

I'm writing in plain C and I have an issue about how to free a pointer to a structure.
I have a structure declared in the following way
typedef struct _RealMatrix {
uint nRows;
uint nCols;
real **matrix;
} RealMatrix;
Now, every time I need it I use the following code to allocate it
RealMatrix *realMatrixAlloc(uint n, uint m) {
loop_var(i);
RealMatrix *matrix;
matrix = malloc(sizeof(RealMatrix));
errcheck(matrix, "Unable to create real matrix structure.");
matrix->nRows = n;
matrix->nCols = m;
matrix->matrix = malloc(n*sizeof(real *));
matrix->matrix[0] = malloc(n*m*sizeof(real));
errcheck(matrix->matrix && matrix->matrix[0], "Unable to get requested memory for real matrix of dimensions: (%u, %u).", n, m);
f_i(i < n) matrix->matrix[i] = matrix->matrix[0] + i*m;
return matrix;
}
where errcheck() is a allocation checking macro. Everything works just fine until I try to deallocate it calling
freeRealMatrix(&myRealMatrix);
which will
free((*ma)->matrix[0]),
free((*ma)->matrix)
free(*ma).
*ma = NULL;
with suitable checks to avoid following any NULL pointer. Here "ma" is the pointer TO THE POINTER to the structure: the function declaration reads
void freeRealMatrix(RealMatrix **ma);
However when this function returns I find out that "myRealMatrix" is still addressing an existing structure, which was not deallocated as I expected by free(*ma). On the other hand the array (*ma)->matrix has been successfully deallocated.
Any ideas about what am I doing wrong? This is driving me crazy...
Thanks in advance!
UPDATE:
I copied the code and executed in a brand new program... It works precisely as expected. I noticed that the address contained in "myRealMatrix" isn't the same as the address pointed by *ma. Well... Sort of: it seems truncated! Instead of being 0x106a50 it is just 0x106a and no more. The last two hex digits are missing every time!
After a free, your pointer continues to contain the address of the freed location. You can not continue addressing this location though. It can be used for something else.
You may want to explicitly set it to NULL after the third free statement:
*ma = NULL;

Resources