realloc strange memory leak - c

I have a n-ary tree:
struct node {
char *data;
int numofkids;
struct node **kids;
}
and a function:
addToParent(struct node *parent, struct node *kid);
that attaches a kid to a parent.
I do that by reallocing the kids array of the father every time I want to add a new kid.
The body:
parent->numofkids ++;
parent->kids = realloc(parent->kids, parent->numofkids * sizeof(char *));
parent->kids[(parent->numofkids) - 1] = kid;
I run my program using valgrind --leak-check=yes ./myprog and it shows memory leaks from realloc function of addToParent function. That means I have to free() something? But what? I am not removing kids, I am just adding the given kid to the given parent.
Valgrind:

The right way to use realloc() is
struct node * temp = realloc(parent->kids, parent->numofkids * sizeof(char *));
if(temp != NULL)
parent->kids = temp;
else
{
/* take necessary action when allocation fails */
}
Because realloc() can fail and if it fails you will end up losing the original data before the realloc() call. Once done using the memory you need to free() it.

There is actually a bunch of potential problems in that code, or in the code calling it (which you haven't shown).
Firstly, the size allocated should be in related to the size of the object being allocated. Not to a multiple of sizeof(char *).
Second, realloc() returns NULL if it fails, and that should be checked for, rather than assuming it succeeds.
Based on these, you need to do something like this
struct node **temp = realloc(parent->kids, (parent->numofkids+1)*sizeof(*temp));
if (temp != NULL)
{
parent->kids = temp;
++parent->numofkids;
parent->kids[parent->numofkids - 1] = kid;
}
else
{
/* reallocation failed, so leave the pointers alone and complain bitterly */
}
The other things to check;
Since you're passing in a pointer to a struct node, check whether the object being passed is valid (e.g. it is not an uninitialised pointer) and that it is being released by the caller when done.
Check that parent points at something value before the first call of your function, and that it is released before the program ends.
Check that ALL of the things you've dynamically allocated (or reallocated) are actually released before the program ends.

Related

Free an array of struct

#include<stdlib.h>
#include <stdio.h>
#include <string.h>
struct t {
int value;
};
int main (void) {
struct t *a = malloc(6*sizeof(struct t));
struct t *b = malloc(sizeof(struct t));
struct t *c = malloc(sizeof(struct t));
c->value = 100;
struct t *d = malloc(sizeof(struct t));
d->value = 100;
struct t *e = malloc(sizeof(struct t));
e->value = 100;
memcpy(b, a, sizeof(*a));
int j = 0;
while (j<6){
a[j] = *c;
j++;
}
int t = 0;
while(t < 6){
free(&a[t]);
t++;
}
free(a);
}
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop. After I changed the second while loop to:
while(t < 6){
printf("%d",a[t].value);
t++;
}
It will run. Any idea how can I free those elements?
Thanks!
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop.
Yes, what's wrong is the attempt to free the elements one by one.
You cannot free allocated memory in different divisions than it was allocated in. The argument to free() must be a pointer value that was previously obtained from an allocation function (and not since freed). The free() call will then free the entire block. It cannot see any subdivisions of that block that you may be using, and it would be unlikely to be able to honor them even if it could see them.
Any idea how can I free those elements?
Free the whole block at once, after you're done with all the data within. That is, just
free(a);
(And also, free(b), free(c), etc.)
One free per malloc'd block.
When you malloc, you are not grabbing memory for each struct. You are grabbing one block (per malloc call) that happens to be large enough to fit 6 structs for a and 1 struct each for the others. You can only free each block of this block at once. In this case you should be freeing a through e (which are addresses returned by malloc assuming you had enough memory).
You could if you really needed to, malloc an array of struct * then malloc blocks into those struct *, but why would you in this case where the struct is small and easily copied?
The key is this: When you allocate a block of memory, malloc (calloc or realloc) will return a pointer to the beginning address in that block. You have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed. free() must be passed the same address returned by malloc().
You can not provide an address from the middle of the allocated block to free(). Why? Because that will not be an address originally returned by a previous call to malloc, calloc or realloc. That is a requirement, see the man-page for free() (man 3 malloc)
The free() function frees the memory space pointed to by ptr, which must have
been returned by a previous call to malloc(), calloc(), or realloc().
So you can only make a call to free() providing a pointer holding an address that was previously allocated and returned by malloc, calloc or realloc. In your case that is a, not &a[1] ... &a[5].

stack implementation using malloc in c [BEGINNER]

for learning purpose I'm implementing a stack with it's functions in c.
I added some small additional functionality to use malloc the first time and try to understand it properly.
I wrote a function which is initially creating my stack struct. The return value of the function is a new struct with an already allocate memory. What is the best way to handle a malloc exception in a function which return value should be a struct? Maybe should I design the function different? I'm aware that the printf is not doing it's job ;)
My Stack struct:
typedef struct Stack
{
int count;
int capacity;
int *data;
} Stack;
Creating a Stack instance:
Stack create_stack(int initialcapacity)
{
Stack new_stack;
new_stack.count = 0;
new_stack.capacity = initialcapacity;
if (!(new_stack.data = malloc(initialcapacity * sizeof(int))))
printf("not enough memory!");
return new_stack;
}
The function is called with the initial capacity of the stack:
Stack stack = create_stack(10);
A second question came up while I was writing a function to delete the Stack instance.
int delete_stack(Stack *stack)
{
stack->count = 0;
stack->capacity = 0;
free(stack->data);
stack->data = NULL;
return 0;
}
Am I able to remove also the struct instance itself? It feels not complete to just set the values back to 0 and direct int* to NULL.
Last but not least, I have a question to my push function. Also here I added some functionality which allows me to push something on the stack while it is already full:
void push(int value, Stack *stack)
{
if (stack->count == stack->capacity)
{
int *temp = malloc(stack->capacity * sizeof(int));
int i;
for (i = 0; i < stack->count; i++)
temp[i] = stack->data[i];
free(stack->data);
stack->data = NULL;
stack->data = malloc(stack->capacity * 2 * sizeof(int));
for (i; i > -1; i--)
stack->data[i] = temp[i];
free(temp);
temp = NULL;
stack->data[stack->count] = value;
stack->count++;
stack->capacity = stack->capacity * 2;
}
else
{
stack->data[stack->count] = value;
stack->count++;
}
}
Is it necessary to "free" the smaller array and put the pointer to NULL before I allocate a new array double the size?
If there is anything from my code which is unnecessary or not written properly, please let me know, I'm grateful for any hint which makes me better.
Cheeers,
me
I would do it with pointers. That is, your create_stack() would allocate a new Stack struct using malloc, then set the values to the struct and usee malloc again to allocate space for the Stack->data. Like this:
Stack* create_stack(int initialcapacity) {
Stack* new_stack = malloc(sizeof(Stack));
if (new_stack == NULL)
return NULL; // return null to tell the caller that we failed
new_stack->count = 0;
new_stack->capacity = initialcapacity;
new_stack->data = malloc(initialcapacity * sizeof(int))
if (new_stack->data == NULL)
{
free(new_stack);
return NULL;
}
return new_stack;
}
With this, we "handle" a malloc error by returning NULL, so the caller knows we failed.
Now that we have used malloc to allocate the Stack struct, you can (read: MUST) free the space taken by it using free(stack); in delete_stack().
In push(), the temporary array is not needed, that is, you could just right away allocate a bigger array, copy the contents to it from the original stack->data, free stack->data and set it to the newly malloc'd array:
int *temp = malloc(stack->capacity * 2 * sizeof(int));
// TODO: what if malloc fails?
int i;
for (i = 0; i < stack->count; i++)
temp[i] = stack->data[i];
free(stack->data);
stack->data = temp;
stack->data[stack->count] = value;
stack->count++;
stack->capacity = stack->capacity * 2;
Q. What is the best way to handle a malloc exception in a function which return value should be a struct?
There are at least three ways:
1) Instead of returning structure itself, return a pointer to it. This means two mallocs: one is for structure itself and another one is for data field. Returning NULL pointer means that something went wrong during construction.
struct Stack* create_stack(int initialcapacity) {
struct Stack* stack = malloc(sizeof(struct Stack));
...
return stack;
}
2) More flexible way is to pass pointer to already allocated structure. Flexibility comes from idea that calling code controls where to allocate structure: on stack or in dynamic memory. Return value of function may be used solely to notify calling code about errors:
bool create_stack(int initialcapacity, struct Stack* stack) {
...
}
// if calling code wants structure on stack (yeah, "stack" on stack)
struct Stack stack;
if (!create_stack(50, &stack)) {
die();
}
// if calling code wants it in dynamic memory
struct Stack* stack = malloc(sizeof(struct Stack));
if (!stack) {
die();
}
if (!create_stack(50, stack)) {
die();
}
3) If your program is not a 10,000+ LOC production code, easiest way may be to simply print error message and abort program immediately if allocation fails. Usually allocation errors are fatal: you can't recover in any meaningful way if there is not enough memory. You may even create a wrapper function over malloc to automatically catch such errors and exit:
void* my_malloc(size_t count) {
void* ptr = malloc(count);
if (ptr == NULL) {
fprintf(stderr, "Allocation failed");
exit(EXIT_FAILURE);
}
return ptr;
}
Q. Am I able to remove also the struct instance itself?
No, you can't. Because it is allocated on stack (the structure itself, not the data). If you want to delete structure itself, you need to use approach #1 from above.
And, by the way, there is no need to set zeroes and NULLs to fields. It doesn't delete anything. Such approach is used rarely and with only purpose to catch bugs (when calling code first deletes some structure and then tries to use it afterwards).
Q. Is it necessary to "free" the smaller array and put the pointer to NULL before I allocate a new array double the size?
Once again, you don't need to NULLify anything -- it doesn't delete anything. Instead of two mallocs and manual copying use realloc, which will do most of the work for you.
Generally, you should be able to declare a structure, then have an array of say 64 of them, with an integer to say which entry is on the top. Very simple, and no dynamic allocation. But 64 is pretty low, That's because stacks, recursion, and levels of nesting are intimately linked. Usually it should be possible to see that 64 is an insane level of nesting, and no legitimate input will ever even approach it. You then might need a guard to protect from malicious or corrupted input, but that just terminates the program or sub-routine.
If you can't establish a low sanity bound on a stack, it might that you still need one. Either it's a rare case where nesting goes very deep, or it's that you haven't approached the problem in the best way, but a sub-optimal program that still works is better than no program.
So you use the same structure, but the stack is set up with a call to
malloc() and, if it grows out of bounds, regrow with a call to realloc().
You might want to still sanity check it, but now sanity checks are
much higher, a million or so as opposed to 64. You also have to check that
realloc does not fail.
typedef struct
{
int x;
char astring[32];
} ENTRY;
static ENTRY *stack = 0;;
static int top = -1;
static int N = 0;
void push(const ENTRY *e)
{
/* grow logic like this */
ENTRY *temp = realloc(stack, newsize * sizeof(ENTRY));
if(temp)
stack = temp;
else
{
/* reallocation has failed but stack still valid */
free(stack);
N = 0;
top = -1;
/* for the sake of argument do this. We need temp to avoid
a memory leak */
fprintf(stderr, "out of memory\n");
}
/* push here, trivial */
}
int pop(ENTRY *e)
{
/* e is a non-const pointer. Fill and reset stack top */
}
You might want the stack global as in the example or you might want to
wrap it in a structure you pass about. Usually you'll want either pointers
or structures on the stack, but occasionally you might need a stack
of integers or floating point values.
There's no good way of handling memory allocation errors in C, especially
ones which can't happen (a computer with several GB of memory installed
is more likely to develop an electrical fault than to run out
of memory when asked for a couple of kilobytes). The usual rule is to
shunt up. But that makes the push call difficult, because every push
could potentially run the computer out of memory (but it can't really,
it's just your encapsulation allows the function to fail).

my program just crushes, using realloc() in recursive function

I have a problem with this code, I tried to understand what's going on, but I cannot understand why it just crushes. the functions works like I expect for the node->left.
But when the last call of the function ends in the case node->left; the function just crushes, I think because of the reallocated array, I don't know if I'm trying to access a forbidden memory.
I'll explain a little more where I think the problem comes from:we are in the last call of helper(node->left,table,len) before printing the array : consider len = N and node->left!=NULL ==> reallocating table len = N+1, assigning node->data to table[len] and everything is fine, node->left == NULL ==> printing the table and we are done with the helper(node->left,table,N) case; now we are in the helper(node->right,table,N) case; in this case the program just crushes ; it's supposed to reallocate table; and assign node->data to table[N]; and so one ...
By the way : this function tries to print all the Root-leaf paths in a binary tree.
struct node {
int data;
struct node* left;
struct node* right;
};
void helper(struct node* node,int *table,int len)
{
if(node == NULL){
return;
}
else{
table = realloc(table,(len+1)*sizeof(int));
table[len]=node->data;
len = len +1;
if(node->left == NULL && node->right == NULL)
{
int cmt=0;
for(cmt = 0; cmt < len ; cmt++ ){
printf("%d ->",table[cmt]);
}
}
else{
helper(node->left,table,len);
helper(node->right,table,len);
}
}
}
void print_rtl(struct node* node) {
if(NULL == node) return;
else{
int *t=malloc(sizeof(int));
t[0]=node->data;
int lenght = 1;
helper(node->left,t,1);
helper(node->right,t,1);
}
}
Here is the thing about realloc: it has the freedom to change not just the size of the allocated memory block, but also its location. In general, realloc can break any pointers you have that are pointing to objects in the block of memory that was realloced. When you try to use those pointers later, you will get undefined behavior.
You should either allocate enough memory at the beginning of your program that you won't need to call realloc, or you should redesign your program so you don't need to allocate that memory block in the first place, or you should make your table pointer be a global variable so that when you change its value, it gets updated for every function that is using the table.
Right now the problem with your code is that when you call helper, it might call realloc and change the location of your table, but it doesn't communicate that change to the caller in any way, so the caller doesn't know where the table is located.
There might be other problems with your code. If you continue to have trouble, I strongly urge you to produce an MCVE and post that in your next question. Doing that makes it much easier for someone else to reproduce your problem and find a solution to it that actually works.
It's hard to tell exactly what going on because it quite a big mess, but generally... The first thing helper() does (after validating node!=NULL) is reallocate table. That means when you get to the recursion point, helper(node->left.. will reallocate, and then immediately after helper(node->right.. will also try to do so, but on an invalid pointer. From there on, it's a wild ride to exceptions...

memory free throws segFault

I am implementing symbol table using link list, The code works fine but there is memory leak in code,
I have following structure
struct node
{
char* pcKey;
void* pvValue;
struct node *next;
};
struct _Sym
{
int totalBindings;
struct node *node;
};
add I have sym_new method to allocate memory for sym instance
sym Sym_new (void)
{
_Sym *m_SymTable_t = (_Sym*) malloc (sizeof(_Sym));
if(m_SymTable_t == NULL)
{
return NULL;
}
else
{
m_SymTable_t->totalBindings = 0;
m_SymTable_t->node = NULL;
return m_SymTable_t;
}//endif
}
I am allocating memory for key and value in other function based on the string length.
The free method is
typedef struct _Sym *Sym;
void Sym_free (Sym m_SymTable_t)
{
assert(m_SymTable_t != NULL);
struct node* temp = m_SymTable_t->node;
struct node *currentBinding = NULL;
while(temp != NULL)
{
currentBinding = temp;
temp = temp -> next;
//Removing comment for the below line throws segfault
//free(currentBinding -> pcKey);
//free(currentBinding -> pvValue);
free(currentBinding);
}
free(m_SymTable_t);
}
What is proper way to free the sym completely?
I have uploaded my symTable_Link.cpp file at link
The variables pcKey and pvValue should probably be initialised to null in the Sym_new() function. Otherwise they may contain any old value. This is because malloc doesn't necessarily zero the memory allocated: it just allocates a chunk of memory and the memory could therefore be filled with junk.
So, if for some reason sym_put() is not called for the newly created object these pointers could point to invalid memory and upon your call to free() segfault. If you initialise them to null free() will just ignore them and won't try to free the memory.
A "hacky" DEBUG-only technique you could use to check that the pcKey and pvValue variables are definitely allocated by a sym_put call would be to initialise them in sym_new with a dummy value, for example 0xCDCDCDCD (careful about pointer-widths here... this is why I'm calling this a hacky technique). Then in sym_free check for this magic constant before freeing pcKey and pvValue. If you find it, there's the problem...
Also of interest may be the thread Do I cast the result of malloc?
EDIT:
Looked at the code linked and you appear to be discarding const!
The function id defined as:
int SymTable_put (SymTable_t m_SymTable_t, const char *pcKey, const void *pvValue)
But then does this cast...
temp->pcKey = (char*)pcKey;
temp->pvValue = (char*)pvValue;
This is a bad idea. You're "fooling" the compiler into invalidating your const promise.
THE BUG:
Ok, so you allocate as follows
temp->pcKey = (char*) malloc (sizeof(char) * strlen (pcKey));
But then you overwrite this pointer using
temp->pcKey = (char*)pcKey;
So you a) have a memory leak and b) have just stashed the wrong pointer, which is probs why you get the segfault. You you probably meant to do instead is (strdup is useful here)...
temp->pcKey = strdup(pcKey);
This will allocate new memory for the string in pcKey and COPY the string into the new memory.
I would hazzard a guess you called the function like this...
SymTable_put (xxx, "KEY string", "VALUE string");
Then your code did this
temp->pcKey = (char*)malloc (sizeof(char) * strlen (pcKey));
...
temp->pcKey = (char*)pcKey;
So now temp->pcKey points to "KEY string" itself and not a copy of it. So when you try to free the string constant, your program complains. What you want to do is copy the string from pcKey into temp->pcKey instead of overwriting the pointer.
EDIT:
As per comments the mallocs need space + 1 to include the null terminator. Also sizeof(char) is always 1, so is redundant. Try strdup instread.

C remove element from dynamic array

I'm trying to write the equivalent of remove for Java's ArrayList in C.
Here is my code. It assumes that index is a valid index in the list.
void arrayListRemove(ArrayList* list, int index){
int i;
if (arrayListSize(list)==1){
list->size = 0;
free(list->data);
list->data = NULL;
} else {
for(i=index;i<arrayListSize(list)-1;i++){
list->data[i] = list->data[i+1];
}
list->data = realloc(list->data, (arrayListSize(list) - 1) * sizeof(void*));
if (list->data != NULL){
--list->size;
} else {
exit(1);
}
}
}
Is this correct?
Would the code work without the arrayListSize(list) == 1 check? I.e. does realloc(list->data, 0) free the arrayList? I've seen conflicting things online about what realloc(ptr, 0) would do.
I would leave the arrayListSize(list) == 1 case. Not relying on the behavior of realloc(ptr, 0) seems prudent, and it makes the code clearer, generally and by using an explicit free.
A few more notes:
When using realloc, be sure to capture the return value in a tmp variable. If realloc fails, then it can return NULL and leave the original pointer untouched. By doing ptr = realloc(ptr); you can cause a memory leak when realloc fails, because you've now lost your original pointer. Instead use this idiom:
tmp = realloc(ptr, newSize);
if (tmp != NULL)
ptr = tmp;
else handleError();
Is it necessary to free the elements of your list when removing them from the list? Your data array consists of pointers, are you leaking memory by not calling free on removed elements? Naturally this isn't necessary in the java implementation. If your list contains the only reference to the contained objects, then you'll need to free them upon remove, or return the pointer in your function and leave it up to the caller to deal with the memory.
There's typically no need to use realloc for shrinking a list, unless you're on a platform that is really memory constrained, and even then, it's probably unnecessary to shrink allocated blocks for every deleted list element. Prefer to grow/shrink your allocated blocks by more than a single element.
This is really a nit, but since this is an API method, and you're using a size member of your data structure to track the list length, you might as well use size throughout, rather than relying on another API method arrayListSize.

Resources