In the following function, I am parsing string form a linked list and giving values to struct array. Is there any way that let me not use mallocs inside while loop.I can not handle glibc errors, so looking for other way.I tried to use char arrays instead of char* for the struct fields. But I am getting seg error. Actually the function is working, but I ahve to call the function 15000 times later, so I want to make sure it won't cause any memory trouble that time.
struct CoordNode
{
int resNum;
double coordX;
double coordY;
double coordZ;
char atomName[4];
};
void parseCrdList()
{
int resNum=1;
int tAtomNum,i;
char *tcoordX, *tcoordY, *tcoordZ, *tatomName, tresNum[5];
ccur_node=headCoord_node->next;
struct CoordNode *t;
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
while (ccur_node!=NULL)
{
tresNum=malloc(5*sizeof(char));
memcpy(tresNum,ccur_node->crdRow+26,4);
resNum=atoi(tresNum);
t[i].resNum=resNum;
tcoordX=malloc(8*sizeof(char));
memcpy(tcoordX,ccur_node->crdRow+35,7);
tcoordY=malloc(8*sizeof(char));
memcpy(tcoordY,ccur_node->crdRow+43,7);
tcoordZ=malloc(8*sizeof(char));
memcpy(tcoordZ,ccur_node->crdRow+51,7);
t[i].coordX=strtod(tcoordX,NULL);
t[i].coordY=strtod(tcoordY,NULL);
t[i].coordZ=strtod(tcoordZ,NULL);
tatomName=malloc(4*sizeof(char));
memcpy(tatomName,ccur_node->crdRow+17,3);
strcpy(t[i].atomName,tatomName);
old_ccur_node=ccur_node;
ccur_node=ccur_node->next;
//free(old_ccur_node);
i++;
}
numofRes=i;
addCoordData(t);
//free(t);
t=NULL;
}
A couple of thoughts and guesses.
First, as I mentioned before, sizeof(char) is always 1 byte in C, it's actually standard byte definition in C. So remove those as completely unnecessary and hard to read.
Back to the main problem.
You never use array of chars bigger than 8, so just make it statically 8 bytes long. If you have to call you function 15k times, that will save you tons of time(malloc takes time to allocate memory for you).
Given information from the question I guess your segfault was the cause of not initialising memory you allocated with malloc or reserved for auto char [8] with its declaration
1. You allocate (or 2nd version - declare 8-byte array) 8 bytes. It works fine. But you get 8 bytes full of trash here.
2. You copy 7 bytes from your list. And that's fine, too. But you forget to NULL terminate, so if you try to print it out back, you get segfault.EDIT If it works then probably you got lucky, because it shouldn't.
Solution
Replace char * witch char [8], remove all mallocs and frees corresponding to those char *, null terminate all your char[8] after strcpy, strncpy, or memcpy (whatever your choice is, depending on how confident you are that your data in list is correct) data to them.
Check your code with valgrind before further use, too.
It's surprising you saying this function worked for you. From what I see from your code I had a lot of memory leaks to begin with because non of those 8-byte mallocs was ever fried.
The second thing is that it looks like you're allocating array of CoordNode before knowing the actual number of data records to parse. I added proper numofRes calculation before allocation.
Since you don't modify input data you don't actually need all those mallocs and memcpy's, you can use crdRow in strtod() immediatly, assuming it has char * type.
The last thing: it's generally a bad practice to do allocation in one place and freeing data in another. So it's better you free your headCoord_node structure in a place where it was allocated, after parsing it. The decision of freeing t depends on how addCoordData(t) treats its parameter.
void parseCrdList()
{
struct CoordNode *t;
int i;
// count number of records to parse
numofRes = 0;
ccur_node = headCoord_node->next;
while (ccur_node != NULL)
{
numofRes++;
ccur_node=ccur_node->next;
}
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
ccur_node = headCoord_node->next;
while (ccur_node!=NULL)
{
t[i].resNum=atoi(ccur_node->crdRow+26);
t[i].coordX=strtod(ccur_node->crdRow+35,NULL);
t[i].coordY=strtod(ccur_node->crdRow+43,NULL);
t[i].coordZ=strtod(ccur_node->crdRow+51,NULL);
strncpy(t[i].atomName,ccur_node->crdRow+17,4);
ccur_node=ccur_node->next;
i++;
}
numofRes=i;
addCoordData(t);
//free(t); // <<< it depends on how addCoordData treats t
}
Related
I need help with a school assignment, specifically with resizing the amount of memory allocated for a pointer WITHOUT realloc.
I have the following declarations in my program.
struct GraphicElement
{
enum{ SIZE = 256 };
unsigned int numLines;
Line* pLines;
char name[SIZE];
};
typedef struct
{
unsigned int numGraphicElements;
GraphicElement* pElements;
}VectorGraphic;
VectorGraphic Image;
As the program runs I'll be adding more GraphicElements to pElements.
For example, after 5 iterations the memory for pElements should be something like this:
[GraphicElement 0][GraphicElement 1] ... [GraphicElement 4]
For the function AddGraphicElement(VectorGraphic* vg) I have this code (with some lines removed for easier reading):
vg->pElements = (GraphicElement*)realloc(vg->pElements, sizeof(GraphicElement)*(vg->numGraphicElements+1));
//Then I assign inputs from user into the members of the struct at vg->pElements[vg->numGraphicElements]
vg->numGraphicElements++;
This works, BUT according to the instructions given by my professor, I'm only allowed to use malloc and free- no realloc. Sadly the only way I've made this work is with realloc.
Can anyone point me in the right direction to implement this using only malloc?
Thanks!
If you are not allowed to use realloc, but malloc and free are allowed, you can replace the call with the following, less efficient, sequence:
void *newData = malloc(newSize);
memcpy(newData, oldData, oldSize);
free(oldData);
Internally, realloc does the same thing, but it does so more efficiently. Unlike user program, realloc knows the actual size of the dynamic memory chunk, so it checks if newSize <= actualSize to avoid reallocation. When actualSize is insufficient, realloc does the same thing as above. realloc has additional logic to deal with situations when the size need to shrink, but in your situation this does not apply.
I am creating a symbol table for a compiler I am writing and when I try adding to my symbol table I keep getting valgrind errors. When I call my function, I am calling my add function
stAdd (&sSymbolTable, "test", RSRVWRD, 4, 9);
and in my stAdd function it is currently
void stAdd (StPtr psSymbolTable, char *identifier, SymbolTableType type,
int addressField, int arrayDimensions)
{
int hashValue;
hashValue = hash (identifier, psSymbolTable->numBuckets);
if (psSymbolTable->spSymbolTable[hashValue] == NULL)
{
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
psSymbolTable->spSymbolTable[hashValue]->entryLevel = psSymbolTable->currentLevel;
psSymbolTable->spSymbolTable[hashValue]->type = type;
psSymbolTable->spSymbolTable[hashValue]->addressField = addressField;
psSymbolTable->spSymbolTable[hashValue]->arrayDimensions = arrayDimensions;
psSymbolTable->spSymbolTable[hashValue]->psNext = NULL;
}
}
But every time I set a value within my StEntry struckt, I get an error
Use of unitialised value of size 8
every time I set something within the if statement. Does any see where I am going wrong?
My StEntry is
typedef struct StEntry
{
char identifier[32];
SymbolTableLevel entryLevel;
SymbolTableType type;
int addressField;
int arrayDimensions;
StEntryPtr psNext;
} StEntry;
This would be a lot easier if I could see the definition of struct StEntry or even the precise valgrind error. But I'll take a wild guess anyway, because I'm feeling overconfident.
Here, you malloc a new StEntry which you will proceed to fill in:
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
This is C, by the way. You don't need to cast the result of the malloc, and it is generally a good idea not to do so. Personally, I'd prefer:
StEntry* new_entry = malloc(sizeof *new_entry);
// Fill in the fields in new_entry
psSymbolTable->spSymbolTable[hashvale] = new_entry;
And actually, I'd ditch the hungarian prefixes, too, but that's an entirely other discussion, which is primarily opinion-based. But I digress.
The next thing you do is:
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
Now, psSymbolTable->spSymbolTable[hashValue]->identifier might well be a char *, which will point to the character string of the identifier corresponding to this symbol table entry. So it's a pointer. But what is its value? Answer: it doesn't have one. It's sitting in a block of malloc'd and uninitialized memory.
So when strcpy tries to use it as the address of a character string... well, watching out for the flying lizards. (If that's the problem, you could fix it in a flash by using strdup instead of strcpy.)
Now, I could well be wrong. Maybe the identifier member is not char*, but rather char[8]. Then there is no problem with what it points to, but there's also nothing stopping the strcpy from writing beyond its end. So either way, there's something ungainly about that line, which needs to be fixed.
I have this struct Exam. and i am using cleanUp function to allocate and free the memory occupied by title but its not freeing it.
typedef struct
{
char* title;
Question* questions[MAX_QUESTIONS];
}Exam;
BOOL CleanUp(Exam * e){
char name[200];
printf("Enter name of the course \n");
gets(name);
fflush(stdout);
e->title = (char*)malloc(sizeof(strlen(name)+1));
strcpy(e->title,name);
free(e->title);
}
sizeof(strlen(name)+1) is not correct, this gives you the size of the result of that calculation, i.e. sizeof(int). Because you have allocated the wrong size you are writing past the end of the buffer.
This is corrupting data and causing free() to fail.
What you mean to do is:
sizeof(char) * (strlen(name) + 1)
In C, sizeof(char) is guaranteed to be 1, so you don't actually need it here, however I've put it there to illustrate the general way to allocate memory for multiple objects: multiply the size of the object by the number of objects.
Surely you simply meant:
e->title = strdup(name);
...
free(e->title);
strdup() will count the string pointed to by 'name', allocate space for a copy (including the null terminator) and copy the data in a sensible, architecture aligned way (usually.)`
I think Whilom Chime gave a pretty adequete answer, as did Mr. Zebra. Another way to do it would be like so;
e->title = malloc(sizeof(char *));
if(e->title != NULL) strcpy(e->title, word);
However, I've found when working with really large data sets (I had to put ~3M words into a 2-3-4 tree a couple days ago), e->title = strdup(word); is actually faster than strcpy(e->title, word);. I don't know why, and it honestly doesn't make sense to me, seeing as strcpy doesn't have to go through the process of allocating memory for the character pointer. Maybe someone else can give input on this
Shown below is a piece of code written in C with an intention of reallocating memory inside a function. I would like to know why this crashes during execution and also an efficient way to do it.
int main()
{
int *kn_row, *kn_col, *uk_row, *uk_col;
double *kn_val, *uk_val;
kn_row=NULL, kn_col=NULL, kn_val=NULL, uk_row=NULL, uk_col=NULL, uk_val=NULL;
evaluate_matrices(&kn_row, &kn_col, &kn_val, &uk_row, &uk_col, &uk_val);
........
}
I tried with two types of function:
evaluate_matrices(int **ptr_kn_row, int **ptr_kn_col, double **ptr_kn_val,
int **ptr_uk_row, int **ptr_uk_col, double **ptr_uk_val)
{
........
/* i,j, and k are calculated */
*ptr_kn_row=(int*)realloc(*ptr_kn_row,k*sizeof(int));
*ptr_kn_col=(int*)realloc(*ptr_kn_col,k*sizeof(int));
*ptr_kn_val=(double*)realloc(*ptr_kn_val,k*sizeof(double));
/* and*/
*ptr_uk_row=(int*)realloc(*ptr_uk_row,j*sizeof(int));
*ptr_uk_col=(int*)realloc(*ptr_uk_col,i*sizeof(int));
*ptr_uk_val=(double*)realloc(*ptr_uk_val,i*sizeof(double));
}
The other way is:
evaluate_matrices(int **ptr_kn_row, int **ptr_kn_col, double **ptr_kn_val,
int **ptr_uk_row, int **ptr_uk_col, double **ptr_uk_val)
{
int *temp1,*temp2,*temp3,*temp4;
double *temp5,*temp6;
..........
temp1 =(int*)realloc(*ptr_kn_row, k*sizeof(*temp1));
if(temp1){*ptr_kn_row = temp1;}
temp2 =(int*)realloc(*ptr_kn_col, k*sizeof(*temp2));
if(temp2){*ptr_kn_col = temp2;}
temp5 =(double*) realloc(*ptr_kn_val, k*sizeof(*temp5));
if(temp5){*ptr_kn_val = temp5;}
......
temp3 = (int*)realloc(*ptr_uk_row, j*sizeof(*temp3));
if(temp3){*ptr_uk_row = temp3;}
temp4 = (int*)realloc(*ptr_uk_col, i*sizeof(*temp4));
if(temp4){*ptr_uk_col = temp4;}
temp6 = (double*)realloc(*ptr_uk_val, i*sizeof(*temp6));
if(temp6){*ptr_uk_val = temp6;}
}
The first function is a minor disaster if memory allocation fails. It overwrites the pointer to the previously allocated space with NULL, thereby leaking the memory. If your strategy for handling out of memory is 'exit at once', this barely matters. If you were planning to release the memory, then you've lost it — bad luck.
Consequently, the second function is better. You're probably going to need to keep track of array sizes, though, so I suspect you'd do better with structures rather than raw pointers, where the structure will contain size information as well as the pointers to the allocated data. You must be able to determine how much space is allocated for each array, somehow.
You also need to keep track of which, if any, of the arrays could not be reallocated – so you don't try to access unallocated space.
I spy with my little eye:
*ptr_kn_val=(double*)realloc(*ptr_kn_val,k*sizeof(int));
^^^^^^^^^^^
I'm sure you meant sizeof(double) and this is just a copy-paste error.
On many systems, int is smaller than double, so if that's the case on yours, this is very likely to be the cause of your crash. That is, undefined behaviour at some point after writing past the end of the memory block.
I know it could be done using malloc, but I do not know how to use it yet.
For example, I wanted the user to input several numbers using an infinite loop with a sentinel to put a stop into it (i.e. -1), but since I do not know yet how many he/she will input, I have to declare an array with no initial size, but I'm also aware that it won't work like this int arr[]; at compile time since it has to have a definite number of elements.
Declaring it with an exaggerated size like int arr[1000]; would work but it feels dumb (and waste memory since it would allocate that 1000 integer bytes into the memory) and I would like to know a more elegant way to do this.
This can be done by using a pointer, and allocating memory on the heap using malloc.
Note that there is no way to later ask how big that memory block is. You have to keep track of the array size yourself.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
/* declare a pointer do an integer */
int *data;
/* we also have to keep track of how big our array is - I use 50 as an example*/
const int datacount = 50;
data = malloc(sizeof(int) * datacount); /* allocate memory for 50 int's */
if (!data) { /* If data == 0 after the call to malloc, allocation failed for some reason */
perror("Error allocating memory");
abort();
}
/* at this point, we know that data points to a valid block of memory.
Remember, however, that this memory is not initialized in any way -- it contains garbage.
Let's start by clearing it. */
memset(data, 0, sizeof(int)*datacount);
/* now our array contains all zeroes. */
data[0] = 1;
data[2] = 15;
data[49] = 66; /* the last element in our array, since we start counting from 0 */
/* Loop through the array, printing out the values (mostly zeroes, but even so) */
for(int i = 0; i < datacount; ++i) {
printf("Element %d: %d\n", i, data[i]);
}
}
That's it. What follows is a more involved explanation of why this works :)
I don't know how well you know C pointers, but array access in C (like array[2]) is actually a shorthand for accessing memory via a pointer. To access the memory pointed to by data, you write *data. This is known as dereferencing the pointer. Since data is of type int *, then *data is of type int. Now to an important piece of information: (data + 2) means "add the byte size of 2 ints to the adress pointed to by data".
An array in C is just a sequence of values in adjacent memory. array[1] is just next to array[0]. So when we allocate a big block of memory and want to use it as an array, we need an easy way of getting the direct adress to every element inside. Luckily, C lets us use the array notation on pointers as well. data[0] means the same thing as *(data+0), namely "access the memory pointed to by data". data[2] means *(data+2), and accesses the third int in the memory block.
The way it's often done is as follows:
allocate an array of some initial (fairly small) size;
read into this array, keeping track of how many elements you've read;
once the array is full, reallocate it, doubling the size and preserving (i.e. copying) the contents;
repeat until done.
I find that this pattern comes up pretty frequently.
What's interesting about this method is that it allows one to insert N elements into an empty array one-by-one in amortized O(N) time without knowing N in advance.
Modern C, aka C99, has variable length arrays, VLA. Unfortunately, not all compilers support this but if yours does this would be an alternative.
Try to implement dynamic data structure such as a linked list
Here's a sample program that reads stdin into a memory buffer that grows as needed. It's simple enough that it should give some insight in how you might handle this kind of thing. One thing that's would probably be done differently in a real program is how must the array grows in each allocation - I kept it small here to help keep things simpler if you wanted to step through in a debugger. A real program would probably use a much larger allocation increment (often, the allocation size is doubled, but if you're going to do that you should probably 'cap' the increment at some reasonable size - it might not make sense to double the allocation when you get into the hundreds of megabytes).
Also, I used indexed access to the buffer here as an example, but in a real program I probably wouldn't do that.
#include <stdlib.h>
#include <stdio.h>
void fatal_error(void);
int main( int argc, char** argv)
{
int buf_size = 0;
int buf_used = 0;
char* buf = NULL;
char* tmp = NULL;
char c;
int i = 0;
while ((c = getchar()) != EOF) {
if (buf_used == buf_size) {
//need more space in the array
buf_size += 20;
tmp = realloc(buf, buf_size); // get a new larger array
if (!tmp) fatal_error();
buf = tmp;
}
buf[buf_used] = c; // pointer can be indexed like an array
++buf_used;
}
puts("\n\n*** Dump of stdin ***\n");
for (i = 0; i < buf_used; ++i) {
putchar(buf[i]);
}
free(buf);
return 0;
}
void fatal_error(void)
{
fputs("fatal error - out of memory\n", stderr);
exit(1);
}
This example combined with examples in other answers should give you an idea of how this kind of thing is handled at a low level.
One way I can imagine is to use a linked list to implement such a scenario, if you need all the numbers entered before the user enters something which indicates the loop termination. (posting as the first option, because have never done this for user input, it just seemed to be interesting. Wasteful but artistic)
Another way is to do buffered input. Allocate a buffer, fill it, re-allocate, if the loop continues (not elegant, but the most rational for the given use-case).
I don't consider the described to be elegant though. Probably, I would change the use-case (the most rational).