Freeing a character pointer - c

I have a function which is called multiple times during the program's execution. In said function, I have a dynamic character pointer which I resize numerous times.
My question is: do I need to free this pointer before the end of the function?
void functionName()
{
char *variable = (char *) malloc(0);
//variable is resized with realloc x number of times
//should free be called here?
return;
}
I should also note that I have tried to free the pointer, however, gdb gives me warnings when I do so.

Yes, you have to free it or you'll leak the memory. Your code should look something like this:
void function(void)
{
char *variable = (char *)malloc(0);
variable = realloc(variable, 10);
// do something with new memory
variable = realloc(variable, 20);
// do something with more new memory
free(variable); // clean up
}
Calling malloc(0) is a little weird, I think.

A few points to make:
I can't see how you use realloc() in your code, but if you're using it like this, it's wrong:
variable = realloc(variable, amount);
When it's unable to allocate more memory, realloc() returns NULL but leaves the original pointer unaltered. In the above line, this means that variable is NULL and we've lost access to the memory it pointed to, but that memory hasn't been freed. The correct idiom is this:
void *tmp = realloc(variable, amount);
if(tmp)
{
// success! variable invalid, tmp has new allocated data
variable = tmp;
}
else
{
// failure! variable valid, but same size as before, handle error
}
The reason you should use the second one is because, with realloc(), failure is bad, but is quite recoverable in many situations, unlike malloc() where failure usually means "stop everything and die."
This is a more contentious issue, but it is questionable whether or not you should cast the return value of malloc() and realloc() like you do. Consider:
// functionally identical in C
char *a = malloc(10);
char *b = (char *)malloc(10);
In C++, the cast must be made, because in C++ void * cannot be implicitly converted to another pointer type. (I think this is a language mistake, but it's not my place to judge.) If your code is C++, you should be using new and delete anyway. If your code is C but needs to compile with C++ compilers (for some inane reason), you have no choice but to cast. If you don't need to compile C code with C++ compilers (which is similar to having to run Ruby code in a Python interpreter), continue to the points below, which are why I think you shouldn't cast.
In C89, if a function is used without being declared, it will be implicitly declared as returning an int. If, say, we forgot to #include <stdlib.h> and we called malloc(), the version without a cast would cause a compiler error (implicit casts from int to char * aren't allowed), while the version with the cast would (wrongly) tell the compiler "I know this sounds crazy, but cast it anyway." Most compilers will give you a warning for implicit (or incompatable) declarations of built-in functions like malloc(), but the cast does make it harder to find.
Say you have some data:
float *array = (float *)malloc(10 * sizeof(float));
Later, you discover that you need more precision on your data, and have to make this a double array. In the above line, you need to change no more than 3 different places:
double *array = (double *)malloc(10 * sizeof(double));
If, on the other hand, you had written:
float *array = malloc(10 * sizeof *array);
You would only need to change float to double in 1 place. Furthermore, always using sizeof *obj instead of sizeof(type) and never using casts means that a later call to realloc() can work without any changes, while using casts and explicit type names would require finding anywhere you called realloc and change the casts and sizeofs. Also, if you forget, and do this:
double *array = (float *)malloc(10 * sizeof(float));
On most platforms, array will now only be an array of 5 elements, assuming the alignment isn't off and the compiler doesn't complain that you're assigning a float * to a double *. Some consider the warning the compiler issues to be helpful, as it points out potentially incorrect lines. However, if we avoid sizeof(type) and avoid casting, we can see that the lines won't be incorrect, so having the compiler draw attention to them is wasting time we could be using to program.

From the man pages:
If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
So, I believe the answer is "yes" :).

Yes you need to call free() once to release the block of memory. You do not need to call free for the subsequent reallocs() that you are doing, even if those return a different address/pointer. The memory manager knows that the old block is not needed any longer and will free() it.

You should be able to just call free(variable) at the end. If realloc ever has to move the data in order to resize it, it calls free internally, you do not need to worry about that.
Also, where you initialize variable, you could just set it to NULL instead of calling malloc; realloc will work just like malloc the first time.

Have a look at some of the answers I have given to a couple of questions in relation to memory management:
Why are memory leaks common?
What's the point in malloc(0)?
C String confusion?
Need help in solving segmentation fault.
C stdlib realloc issue?
C: Creating array of strings from delimited strings.
All of the above point out the obvious thing, for every malloc there is a free, if not you have a memory leak, so it is imperative that you free the memory when you are finished with your pointer variable that is mallocd.
Hope this helps,
Best regards,
Tom.

int main(int argc, char *argv[])
{
char *p = malloc(sizeof(argv[1]));
p = argv[1];
printf("%s\n", p);
free(p);
return 0;
}
iam getting the glibc error
hello
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x00007fff66be94c6 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f38dca1db96]
./a.out[0x4005ed]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f38dc9c076d]

Related

do I need to allocate space for pointer as well as space for memory area whose address will be kept in pointer in pointer to pointer and realloc

I have this code
int main(int argc, char *argv[])
{
int i=1;
char **m=malloc(sizeof(char *)*i);
printf("%zu\n",sizeof *m);
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
i=2;
m=(char **)realloc(m,sizeof (char *)*i);
m[1]=malloc(strlen("hi")+1);
strcpy(m[1],"hi");
printf("%s %s \n",m[0],m[1] );
// TODO: write proper cleanup code just for good habits.
return 0;
}
this is how I am allocating pointer char **m 8 byte single char pointer
int i=1;
char **m=malloc(sizeof(char *)*i);
and this is how I am allocating area of space whose address will be kept in m[0]
m[0]=malloc(strlen("hello")+1);
strcpy(m[0],"hello");
printf("%s\n", m[0]);
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1); and does this m[1]=malloc(strlen("hi")+1); this *(m+1)=malloc(strlen("hi")+1);
And I am increasing pointer to pointer numbers like this in allocation m=(char **)realloc(m,sizeof (char *)*i); before m[1]=malloc(strlen("hi")+1);
is there anything wrong with above code. I seen similar code on this Dynamic memory/realloc string array
can anyone please explain with this statement char **m=malloc(sizeof(char *)*i); I am allocating 8 byte single pointer of type char but with this statement m=(char **)realloc(m,sizeof (char *)*i); why I am not getting stack smaching detected error. How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
I like to know is this normally how its done. I mean allocating space for pointer and then allocating space in memory that the pointer will hold.
It depends on what you are trying to achieve. If you wish to allocate an unspecified amount of strings with individual lengths, then your code is pretty much the correct way to do it.
If you wish to have a fixed amount of strings with individual lengths, you could just do char* arr [n]; and then only malloc each arr[i].
Or if you wish to have a fixed amount of strings with a fixed maximum length, you could use a 2D array of characters, char arr [x][y];, and no malloc at all.
Does m[0]=malloc(strlen("hello")+1); is same as this *(m+0)=malloc(strlen("hello")+1);
Yes, m[0] is 100% equivalent to *((m)+(0)). See Do pointers support "array style indexing"?
is there anything wrong with above code
Not really, except stylistic and performance issues. It could optionally be rewritten like this:
char** m = malloc(sizeof(*m) * i); // subjective style change
m[0]=malloc(sizeof("hello")); // compile-time calculation, better performance
why I am not getting stack smaching detected error
Why would you get that? The only thing stored on the stack here is the char** itself. The rest is stored on the heap.
How exactly realloc works. can anyone give me the link of realloc function or explain a bit on this please
It works pretty much as you've used it, though pedantically you should not store the result in the same pointer as the one passed, in case realloc fails and you wish to continue using the old data. That's a very minor remark though, since in case realloc fails, it either means that you made an unrealistic request for memory, or that the RAM on your system is toast and you will unlikely be able to continue execution anyway.
The canonical documentation for realloc would be the C standard C17 7.22.3.5:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. The contents of the new
object shall be the same as that of the old object prior to deallocation, up to the lesser of
the new and old sizes. Any bytes in the new object beyond the size of the old object have
indeterminate values.
If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.
Notably there is no guarantee that the returned pointer always has the same value as the old pointer, so correct use would be:
char* tmp = realloc(arr, size);
if(tmp == NULL)
{
/* error handling */
}
arr = tmp;
(Where tmp has the same type as arr.)
Your code looks fine to me. Yes, if you are storing an array of strings, and you don't know how many strings will be in the array in advance, then it is perfectly fine to allocate space for an array of pointers with malloc. You also need to somehow get memory for the strings themselves, and it is perfectly fine for each string to be allocated with its own malloc call.
The line you wrote to use realloc is fine; it expands the memory area you've allocated for pointers so that it now has the capacity to hold 2 pointers, instead of just 1. When the realloc function does this, it might need to move the memory allocation to a different address, so that is why you have to overwrite m as you did. There is no stack smashing going on here. Also, please note that pointers are not 8 bytes on every platform; that's why it was wise of you to write sizeof(char *) instead of 8.
To find more documentation about realloc, you can look in the C++ standard, or the POSIX standard, but perhaps the most appropriate place for this question is the C standard, which documents realloc on page 314.

Do I need to/can I free a void pointer in C?

I have a void pointer as a parameter for a function. It is currently pointing to an int. When I try to free it, it returns a bus error. Should I be freeing void pointers? If so, how do I do so?
You have to answer two questions first:
Was it previously allocated with a malloc family function (e.g. calloc)?
Did you inherit ownership of it when making the function call?
If the answer to both of those is "Yes", then it's at your discretion, though presumably you'd do it at the appropriate time and place to avoid "use after free" type bugs.
When you inherit ownership of a pointer you inherit the responsibility for calling free() when you're done using it, or passing on ownership to another part of your code. If you fail in this responsibility you have memory leaks.
As a general rule you should never free() a pointer unless you know with certainty that's what you're supposed to do, and you're allowed to do it.
Some functions return pointers to things that you do not own, and even if you did, they're not valid for free() because they may be offset somehow. Only the original pointer returned from the malloc-type function can be used with free().
For example:
void* getBuffer(size_t size) {
globalBufferOffset += size;
return &globalBuffer[globalBufferOffset];
}
This returns a pointer in the middle of some structure that may or may not be dynamically allocated. You don't own it. You should not call free() on it.
Read the documentation very carefully to understand your responsibilities. You may need to call a special free-type function when you're done with the pointer. You may not. You may need to pay attention to thread safety. There's a lot of things that can be going on here you need to be aware of before making a decision.
If the pointer is allocated by malloc or something like that, you have to free.
Because, the malloc function returns the void * pointer, so YES, you can/need to free this pointer.
There are some cases you should not free, for example, the code below:
#include <stdio.h>
#include <stdlib.h>
int main()
{
void *p1, *p2, *p3;
int x, y;
p1 = &x;
p2 = malloc(sizeof(int));
p3 = malloc(10);
*(int*)p2 = y;
p3 = "abc";
free(p1); // it raises the fault because p1 is not allocated by malloc
free(p2); // it's OK
free(p3); // it raises also the fault because p3 points to string literal
return 0;
}
You need a corresponding delete each new or a free for each malloc.
If you never wrote a new or a malloc you don't need a free.
Some libraries have their own version of new and free. They would also have corresponding methods and hopefully some documentation. Like SDL_CreateRGBSurface and SDL_FreeSurface.

Is it good coding practice to assign the address returned by realloc() to the same pointer?

I saw some code related to realloc() on some sites as below.
int *p = (int *)malloc(sizeof(int) * 10);
p = (int *)realloc(p, 100);
But as the standard says, if realloc fails, the original block is left untouched and it returns NULL.
So if realloc fails, from above example, we will lose the ability to free p. Can any one please let me know is it good coding practice to assign the address returned by realloc() to the same pointer?
You are correct that directly assigning the return value of realloc to your only copy of the original pointer is a bad practice. Not only do you lose the ability to free the memory if realloc failed (I would call this the lesser issue); you also lose the data that your pointer pointed to.
For some programs this may not matter (e.g. if you're just going to terminate and abort the entire operation on allocation failures, which may or may not be acceptable practice, and which is a whole topic in itself) but in general you need to first store the result of realloc to a separate temp variable, and only overwrite the original pointer variable after you check that it succeeded.
R. gave a clear answer to your question. Let me emphasize two other issues in the code fragment:
int *p = (int *)malloc(sizeof(int) * 10);
p = (int *)realloc(p, 100);
It is mostly considered bad practice in C to cast the return value of malloc(), calloc() and realloc(). The void * return value will automatically be converted to the appropriate pointer type, unless the code is compiled as C++ code, which is an estranged cousin of C.
More importantly, it does not make sense to realloc the pointer to a hardcoded size 100. The number of ints that will be accessible in the reallocated array will depend on the actual size of the int type, which can vary from one system to another. Indeed on some architectures, 100 is not even a multiple of sizeof(int). The author might have meant to write p = realloc(p, sizeof(int) * 100); or p = realloc(p, sizeof(*p) * 100);, and more context around the fragment could help understand the intent... As written, it is very likely a bug, for multiple reasons.

How to prevent dangling pointers/junk in c?

I'm new to C and haven't really grasped when C decides to free an object and when it decides to keep an object.
heap_t is pointer to a struct heap.
heap_t create_heap(){
heap_t h_t = (heap_t)malloc(sizeof(heap));
h_t->it = 0;
h_t->len = 10;
h_t->arr = (token_t)calloc(10, sizeof(token));
//call below a couple of times to fill up arr
app_heap(h_t, ENUM, "enum", 1);
return h_t;
}
putting h_t through
int app_heap(heap_t h, enum symbol s, char* word, int line){
int it = h->it;
int len = h->len;
if (it + 1 < len ){
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
h->arr[it].word = word;
h->arr[it].line = line;
h->it = it + 1;
printf(h->arr[it].word);
return 1;
} else {
h->len = len*2;
h->arr = realloc(h->arr, len*2);
return app_heap(h, s, word, line);
}
}
Why does my h_t->arr fill up with junk and eventually I get a segmentation fault? How do I fix this? Any C coding tips/styles to avoid stuff like this?
First, to answer your question about the crash, I think the reason you are getting segmentation fault is that you fail to multiply len by sizeof(token) in the call to realloc. You end up writing past the end of the block that has been allocated, eventually triggering a segfault.
As far as "deciding to free an object and when [...] to keep an object" goes, C does not decide any of it for you: it simply does it when you tell it to by calling free, without asking you any further questions. This "obedience" ends up costing you sometimes, because you can accidentally free something you still need. It is a good idea to NULL out the pointer, to improve your chance of catching the issue faster (unfortunately, this is not enough to eliminate the problem altogether, because of shared pointers).
free(h->arr);
h -> arr = NULL; // Doing this is a good practice
To summarize, managing memory in C is a tedious task that requires a lot of thinking and discipline. You need to check the result of every allocation call to see if it has failed, and perform many auxiliary tasks when it does.
C does not "decide" anything, if you have allocated something yourself with an explicit call to e.g. malloc(), it will stay allocated until you free() it (or until the program terminates, typically).
I think this:
token temp;
h->arr[it] = temp;
h->arr[it].sym = s;
/* more accesses */
is very weird, the first two lines don't do anything sensible.
As pointed out by dasblinkenlight, you're failing to scale the re-allocation into bytes, which will cause dramatic shrinkage of the array when it tries to grow, and corrupt it totally.
You shouldn't cast the return values of malloc() and realloc(), in C.
Remember that realloc() might fail, in which case you will lose your pointer if you overwrite it like you do.
Lots of repetition in your code, i.e. realloc(h->arr, len*2) instead of realloc(h->arr, h->len * sizeof *h->arr) and so on.
Note how the last bullet point also fixes the realloc() scaling bug mentioned above.
You're not reallocating to the proper size, the realloc statement needs to be:
realloc(h->arr, sizeof(token) * len*2);
^^^^^^^^^^^^
(Or perhaps better realloc(h->arr, sizeof *h->arr * h->h_len);)
In C, you are responsible to free the memory you allocate. You have to free() the memory you've malloc/calloc/realloc'ed when it's suitable to do so. The C runtime never frees anything, except when the program has terminated(some more esoteric systems might not release the memory even then).
Also, try to be consistent, the general form for allocating is always T *foo = malloc(sizeof *foo), and dont duplicate stuff.
e.g.
h_t->arr = (token_t)calloc(10, sizeof(token));
^^^^^^^^ ^^ ^^^^^^^^^^^^^
Don't cast the return value of malloc in C. It's unncessesary and might hide a serious compiler warning and bug if you forget to include stdlib.h
the cast is token_t but the sizeof applies to token, why are they different, and are they the same type as *h_t->arr ?
You already have the magic 10 value, use h_t->len
If you ever change the type of h_t->arr, you have to remember to change the sizeof(..)
So make this
h_t->arr = calloc(h_t->len, sizeof *h_t->arr);
Two main problems in creating dangling pointers in C are the not assigning
NULL to a pointer after freeing its allocated memory, and shared pointers.
There is a solution to the first problem, of automatically nulling out the pointer.
void SaferFree(void *AFree[])
{
free(AFree[0]);
AFree[0] = NULL;
}
The caller, instead calling
free(p);
will call
SaferFree(&p);
In respect to the second and harder to be siolved issue:
The rule of three says:
If you need to explicitly declare either the destructor, copy constructor or copy assignment operator yourself, you probably need to explicitly declare all three of them.
Sharing a pointer in C is simply copying it (copy assignment). It means that using the rule of three (or the general rule of 0)
when programming in C obliges the programmer to supply a way to construct and especially destruct such an assignment, which is possible, but not an
easy task especially when C does not supply a descructor that is implicitly activated as in C++.

Why do I get different results when I dereference a pointer after freeing it?

I've a question about the memory management in C (and GCC 4.3.3 under Debian GNU/Linux).
According to the C Programming Language Book by K&R, (chap. 7.8.5), when I free a pointer and then dereference it, is an error. But I've some doubts since I've noted that sometimes, as in the source I've pasted below, the compiler (?) seems to work according a well-defined principle.
I've a trivial program like this, that shows how to return an array dynamically allocated:
#include <stdio.h>
#include <stdlib.h>
int * ret_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i*2;
}
printf("Address pointer in ret_array: %p\n", (void *) arr);
return arr;
}
int * ret_oth_array(int n)
{
int * arr = (int *) malloc(10 * sizeof(int));
int i;
for (i = 0; i < n; i++)
{
arr[i] = i+n;
}
printf("Address pointer in ret_oth_array: %p\n", (void *) arr);
return arr;
}
int main(void)
{
int *p = NULL;
int *x = NULL;
p = ret_array(5);
x = ret_oth_array(6);
printf("Address contained in p: %p\nValue of *p: %d\n", (void *) p, *p);
free(x);
free(p);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
If I try to compile it with some arguments: -ansi -Wall -pedantic-errors, it doesn't raises errors or warning. Not only; it also runs fine.
Address pointer in ret_array: 0x8269008
Address pointer in ret_oth_array: 0x8269038
Address contained in p: 0x8269008
Value of *p: 0
Memory freed.
*p+4 = 8
*x = 0
*(p+4) is 8 and *x is 0.
Why does this happen?
If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
Another strange thing happens if I try to change the order of the calls to free.
E.g.:
int main(int argc, char * argv[])
{
/* ... code ... */
free(p);
free(x);
printf("Memory freed.\n");
printf("*(p+4) = %d\n", *(p+4));
printf("*x = %d\n", *x);
return 0;
}
In fact in this case the output (on my machine) will be:
*p+4 = 8
*x = 142106624
Why does the x pointer is really "freed", while the p pointer is freed (I hope) "differently"?
Ok, I know that after freeing memory I should make the pointers to point to NULL, but I was just curious :P
It is undefined behaviour, so it is an error to deference freed pointer as strange things may (and will) happen.
free() doesn't change the value of the pointer so it keeps pointing to the heap in the process address space - that's why you don't get segfault, however it is not specified and in theory on some platforms you can get segfault when you try to dereference pointer immediately after freeing.
To prevent this it is a good habit to assign pointer to NULL after freeing so it will fail in predictable way - segfault.
Please note that on some OSes (HP-UX, may be some others as well) it is allowed to dereference NULL pointer, just to prevent segfault (and thus hiding problems). I find it rather stupid as it makes things much more difficult to diagnose, although I don't know the full story behind this.
free() (and malloc()) are not from gcc. They come from the C library, which on Debian is usually glibc. So, what you are seeing is glibc's behavior, not gcc's (and would change with a different C library, or a different version of the C library).
I particular, after you use free() you are releasing the memory block malloc() gave you. It's not yours anymore. Since it is not supposed to be used anymore, the memory manager within glibc is free to do whatever it wants with the memory block, including using parts of it as its own memory structures (which is probably why you are seeing its contents change; they have been overwritten with bookkeeping information, probaly pointers to other blocks or counters of some sort).
There are other things that can happen; in particular, if the size of your allocation was large enough, glibc can ask the kernel for a separate memory block for it (with mmap() or similar calls), and release it back to the kernel during the free(). In that case, your program would crash. This can in theory also happen in some circunstances even with small allocations (glibc can grow/shrink the heap).
This is probably not the answer you are looking for, but I'll give it a try anyway:
Since you're playing with undefined behaviour that you should never depend on in any way, shape or form, what good does it do to know how exactly one given implementation handles that?
Since gcc is free to change that handling at any given time, between versions, architectures or depending on the position and brightness of the moon, there's no use whatsoever in knowing how it handles it right now. At least not to the developer that uses gcc.
*(p+4) is 8 and *x is 0. Why does this happen? If *(p+4) is 8, shouldn't *x be 6, since the first element of the x-array is 6?
One possible explanation for this would be that printf("...%i..."...) might internally use malloc to allocate a temporary buffer for it's string interpolation. That would overwrite the contents of both arrays after the first output.
Generally, I would consider it an error if a program relies on the value of a pointer after it has been freed. I would even say that it's a very bad code smell if it keeps the value of a pointer after it has been freed (instead of letting it go out of scope or overwriting it with NULL). Even if it works under very special circumstances (single-threaded code with a specific heap manager).
Once you free the dynamic-memory variable, it is not yours. The memory manager is free to do what ever it sees better with that piece of memory you where pointing to. The compiler doesn't do anything as far as I know with the freed blocks of memory, because it is a function and not defined by the language. Even if it is defined by the languages, the compiler just inserts calls to the underlying OS functions.
Just wanna say, It is undefined by the language, So you have to check your OS and watch that piece of memory after freeing it. The behavior maybe random, because sometimes other programs ask for memory, sometimes not!
by the way, It is different on my machine, the value changes for both pointers.
Although the behavior you're seeing seems to be consistent, it is not guaranteed to be so. Unforeseen circumstances may causes this behavior to change (let alone the fact that this is completely implemetnatation dependent).
Specifically, in your example you free() the array and then get the old content when you access the array. If you'll have additional malloc() calls after the free() - chances are that the old contents will be lost.
Even if the memory is freed, it is not necessarily reused for some other purpose. Old pointers to your process memory are still valid pointers (though to unallocated memory) so you do not get segmentation faults either.

Resources