realloc() Failure - c

I was trying to implement a simple function that can concatenate any number of strings passed to it. My call to realloc fails. Is it something to do with the fact that the string arguments that i pass to the function are stored in data segment where as realloc looks to allocate memory from the heap ? This is just an idea i have. I'm a beginner so please excuse if it seems stupid. How can i make this function run ?
//Program to implement a function that can concatenate any number of argumnets
#include<stdio.h>
#include<stdarg.h>
#include<string.h>
#include<stdlib.h>
char *mstrcat(char *first, ...);
int main(int argc, int **argv){
char *s;
s=mstrcat("I ","Love ","Stack","Overflow");
printf("%s\n",s);
}
char *mstrcat(char *first, ...){
char *s=first,*p;
int len=0; // stores the length of the string as it grows
len=strlen(s);
va_list aptr; // creates a pointer to the unnamed argument list
va_start(aptr,first); // initialise aptr to the first unnamed argument
if(aptr==NULL){
return s;
}
while((p=va_arg(aptr,char *))!=NULL){ // till there are no more arguments to process
len+=strlen(p);
if((s=(char *)realloc(s,len+1))!=NULL){
strcat(s,p);
}
else{
printf("Failed to concatenate\n");
return first;
}
}
return s;
}

Your code has an Undefined Behavior. The standard mandates that the pointer being passed to realloc should exactly match the pointer which was allocated dynamic memory using a memory management function. Memory management functions specified by the standard are:
aligned_alloc, calloc, malloc, and realloc.
The pointer you are passing to realloc() was not returned by any of these and hence the Undefined Behavior.
Reference:
c99 standard: 7.22.3.5 The realloc function
Synopsis: #1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
#3
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.

A point about realloc, the size argument is new size of the allocated data, which for you should be the old length of s plus the length of p (+1 for the terminator of course).
And as you suspect, you can not use the first string as the base of the reallocations. Instead set s to NULL at the start of the function.

You are passing string literals to your mstrcat function, and they are probably stored in a read-only area of the process, which means that they cannot be modified or resized.
realloc can only be used with a pointer previously returned by malloc or realloc. Other kinds of uses (as is yours) yield undefined behaviour.

the mstrcat function is starting with s pointing to the first argument. Then you are trying to realloc() this pointer which is a static string. This will not work. You can only realloc a pointer previously allocated by malloc().
I suggest you change char *s=first to char *s=strdup(first) to allocate a copy of the first argument, and then this code should work.
The concatenation algorithm is pretty inefficient, but that's another story... (hint: you may want to enumerate the arguments and keep track of the total size, then alloc() a corresponding buffer and then concatenate all the arguments into it)

Related

Free a void ** pointer

I'm writing code to free a generic double pointer in C (void **ptr). How do I check to see if the pointer was allocated via malloc/calloc? How do I free the internal pointers? (I learned to do this by using a for loop and being given the number of members in the pointer, but I am not given that here.). The function declaration is
void freeArray(void **ptr);
How would you go about freeing this pointer, and error checking to make sure you won't get a seg fault or memory leak or other memory error?
I'm writing code to free a generic double pointer in C (void **ptr).
I believe there is not such thing as a generic double pointer. A pointer is just that: a pointer.
How do I check to see if the pointer was allocated via malloc/calloc?
You do not. A pointer is not allocated. Memory is allocated and the address of the area is assigned to a pointer.
How do I free the internal pointers? (I learned to do this by using a
for loop and being given the number of members in the pointer, but I
am not given that here.). The function declaration is
void freeArray(void **ptr);
"Internal pointer" is not a great description for this use, I believe.
Anyway, compare your function prototype with the usual main() prototype
int main(int argc, char** argv)
and you will see something is missing here.
Maybe it is more clear if you write
void** ptr = NULL;
You are declaring ptr. As a pointer. But ptr is allocated by now. It is static. May be 4 may be 8 bytes. And it points to a pointer to void. Just this.
ptr is void**, *ptr is void*, **ptr is void. When using ptr as a block of pointers you must do the same as the system does with main(): build the block and keep your own argc, the count of values. It is your problem to do that, or better, it is you problem NOT to do that.
Try this:
void freeArray(int ptrc, void** ptr);
And keep this pair always together and updated, so the part of "being given the number of members in the pointer" is a no brainer.
There is no portable way to determine if ptr points to an allocated block or not, nor how large this block is, nor whether the pointers in this block are valid and point to allocated memory.
freeArray is given a pointer to an array of void pointers. Since there is no information about the number of pointers to free, an assumption must be made:
either the number of pointers is fixed. Say your program is dealing with arrays of 3 pointers everywhere, freeArray might be assumed to free 3 pointers...
or the array could be null terminated, such as the argv array passed to main. Note however that this particular array of strings is not meant to be freed this way.
Look at the code that allocates the arrays and determine which convention is used.
Here is a naive implementation of freeArray() for a null terminated allocated array of pointers to allocated blocks:
void freeArray(void **ptr) {
if (ptr) {
for (size_t i = 0; ptr[i]; i++) {
free(ptr[i]);
}
free(ptr);
}
}
freeing pointer does not change wether it's allocated using malloc or calloc, if you wanna free array of pointers you should know before length of it. unless you now that the last element of the array is NULL so you can loop and stop when encounter NULL.

Need some explanation about malloc

I don't understand it prints out OneExample when i allocated memory for 5.
I know it is possible to do it using strncpy
But is there a way to do it without using strncpy
It works with strncpy, but is there a way to do it without strncpy ?
void main()
{
char *a;
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
}
It prints out OneExample
Should not it print OneE ??
Can someone explain ?
void main()
{
char *a;
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
}
You aren't using the memory you've allocated. After allocating the memory, you override the pointer a with a pointer to a string literal, causing a memory leak. The subsequent call to free may also crash your application since you're calling free on a pointer that was not allocated with malloc.
If you want to use the space you allocated, you could copy in to it (e..g, by using strncpy).
I don't understand it prints out OneExample when i allocated memory for 5. I know it is possible to do it using strncpy But is there a way to do it without using strncpy
It works with strncpy, but is there a way to do it without strncpy ?
You can use memcpy() as an alternative.
Read about memcpy() and check this also.
Seems that you have some misunderstanding about pointers in C.
Look at this part of your code:
a=(char*)malloc(5);
a="OneExample";
printf("%s",a);
free(a);
You are allocating memory to char pointer a and then immediately pointing it to the string literal OneExample.
This is memory leak in your code because you have lost the reference of the allocated memory.
You should be aware of that the free() deallocates the space previously allocated by malloc(), calloc() or realloc() otherwise the behavior is undefined.
In your program, you are trying to free memory of string literal "OneExample" which will lead to undefined behavior.
Using memcpy(), you can do:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
char *a = malloc(5);
if (a == NULL) {
fprintf (stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
memcpy (a, "OneExample", 4); // copy 4 characters to a, leaving space for null terminating character
a[4] = '\0'; // make sure to add null terminating character at the end of string
printf("%s\n",a);
free(a);
return 0;
}
Additional:
Using void as return type of main function is not as per standards. The return type of main function should be int.
Follow good programming practice, always check the malloc return.
Do not cast the malloc return.
To use malloc, you need to #include <stdlib.h> which you don't show in your code. The reason is that malloc has a prototype returning a void * and without that prototype, your compiler is going to assume it returns an int. In 64bit architectures, this is a problem, as void * is a 64bit type, and int is 32bit. This makes that the code that extracts the value returned by malloc() to take only the 32 less signifiant bits of the result, and then convert them to a pointer (as per the cast you do, that you shouldn't ---see a lot of comments about this---, and you'll avoid the error you should have got, about trying to convert a int value into a char * without a cast)
After assigning the pointer given by malloc(3) into a, you overwrite that pointer with the address of the string literal "OneExample". This makes two things:
First, you lose the pointer value given by malloc(3) and that was stored in a so you don't have it anymore, and you'll never be able to free(3) it. This is called a memory leak, and you should avoid those, as they are programming errors.
This will be making some kind of undefined behaviour in the call to free(3) that only accepts as parameter a pointer value previously returned by malloc (and this is not the actual address stored in a) Probably you got some SIGSEGV interrupt and your program crashed from this call.
When you do the assignment to a, you are just changing the pointer value that you stored in there, and not the deferred memory contents, so that's what makes sense in calling strcpy(3), because it's the only means to copy a string of characters around. Or you can copy the characters one by one, as in:
char *a = malloc(5); /* this makes a memory buffer of 5 char available through a */
int i;
for(i = 0; i < 4 /* see below */; i++)
a[i] = "OneExample"[i]; /* this is the copy of the char at pos i */
a[i] = '\0'; /* we must terminate the string if we want to print it */
the last step, is what makes it necessary to run the for loop while i < 4 and not while i < 5, as we asked malloc() for five characters, and that must include the string terminator char.
There's one standard library alternative to this, and it is:
char *a = strdup("OneExample");
which is equivalent to:
#define S "OneExample"
char *a = malloc(strlen(S) + 1); /* see the +1 to allow for the null terminator */
strcpy(a, S);
but if you want to solve your example with the truncation of the string at 5, you can do the following:
char *dup_truncated_at(const char *s, int at)
{
char *result = malloc(at + 1); /* the size we need */
memcpy(result, s, at); /* copy the first at chars to the position returned by malloc() */
result[at] = '\0'; /* and put the string terminator */
return result; /* return the pointer, that must be freed with free() */
}
and you'll be able to call it as:
char *a = dup_truncated_at("OneExample", 5);
printf("truncated %s\n", a);
free(a); /* remember, the value returned from dup_truncated_at has been obtained with a call to malloc() */
You need to be clear about what your pointer points to. First, you declare a char *a;. This is a pointer to a character.
In the line a=(char*)malloc(5);, you allocate a bit of memory with malloc and assign the location of that memory to the pointer a. (a bit colloquial, but you understand what I mean). So now a points to 5 bytes of freshly allocated memory.
Next, a="OneExample";. a gets a new value, namely the location of the string OneExample; There is now no longer a pointer available to the five bytes that were allocated. They are now orphans. a points to a string in a static context. Depending on the architecture, compiler and a lot of other things, this may be a static data space, program space or something like that. At least not part of the memory that is used for variables.
So when you do printf("%s",a);, a points to the string, and printf will print-out the string (the complete string).
When you do a free(a);, you are trying to free a part of the program, data etc space. That is, in general, not allowed. You should get an error message for that; in Linux that will be something like this:
*** Error in `./try': free(): invalid pointer: 0x000000000040081c ***
======= Backtrace: =========
/lib64/libc.so.6(+0x776f4)[0x7f915c1ca6f4]
/lib64/libc.so.6(+0x7ff4a)[0x7f915c1d2f4a]
/lib64/libc.so.6(cfree+0x4c)[0x7f915c1d6c1c]
./try[0x400740]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7f915c1737d0]
./try[0x4005c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 21763273 /home/ljm/src/try
00600000-00601000 r--p 00000000 08:01 21763273 /home/ljm/src/try
00601000-00602000 rw-p 00001000 08:01 21763273 /home/ljm/src/try
[- more lines -]
The statement a="OneExample"; does not mean “Copy the string "OneExample" into a.”
In C, a string literal like "OneExample" is an array of char that the compiler allocates for you. When used in an expression, the array automatically becomes a pointer to its first element.1
So a="OneExample" means “Set the pointer a to point to the first char in "OneExample".”
Now, a is pointing to the string, and printf of course prints it.
Then free(a) is wrong because it attempts to free the memory of "OneExample" instead of the memory provided malloc.
Footnote
1 This automatic conversion does not occur when a string literal is the operand of sizeof, is the operand of unary &, or is used to initialize an array.
the = does not copy the string only assigns the the new value to the pointer overriding the old one. You need to allocate sufficient memory to store the string and then copy it into the allocated space
#define MYTEXT "This string will be copied"
char *a = malloc(strlen(MYTEXT) + 1); //+1 because you need to store the trailing zero
strcpy(a,MYTEXT);
then you can free a when not needed anymore
Firstly here
a=(char*)malloc(5);
you have allocated 5 bytes of memory from heap and immediately
a="OneExample";
override previous dynamic memory with string literal "OneExample" base address due to that a no longer points to any dynamic memory, it causes memory leak(as no objects points that dynamic memory, it lost) here and even after that
free(a);
freeing not-dynamically allocated memory causes undefined behavior.
side note, do read this Why does malloc allocate more memory spaces than I ask for & Malloc vs custom allocator: Malloc has a lot of overhead. Why? to get some more info about malloc().

Freeing char[] in C gives error and how do C compiler handle that char[]

Although arrays are basically pointers, freeing char[] in C gives an error.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this gives error at run time
}
ERROR: nexc(4212,0x10038e3c0) malloc: * error for object 0x7fff5fbff54c: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
The interesting part is that, it is saying I am freeing a pointer which is not allocated.
How could this happen?
But in C++, compiler gives me a compile time error instead.
int main(void) {
char ptr[] = "Hello World";
delete ptr; // this gives error at compile time
}
like,
Cannot delete expression of type char[12]
I thought this is because of compiler handles the char[12] by allocating when the function is called and deallocating the memory when the function ends. So, I write some codes after free(ptr); before the function ends.
#include <stdlib.h>
int main(void) {
char ptr[] = "Hello World";
free(ptr); // this still gives error at run time
printf("\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
}
This still gives error. How is this happening?
You only free what you have allocated using malloc (directly or indirectly) or related function (like realloc).
Attempting to pass a pointer not returned by malloc will lead to undefined behavior.
That you get a compiler error for delete in C++ is first and foremost because C and C++ are different languages with different rules.
And remember, an array is an array, not a pointer. Though an array can decay to a pointer to its first element in many situation (like when passing it to a function).
You only call free on dynamic memory that you've allocated using malloc, calloc &c.. Similarly, you only call delete on memory allocated with new. In your case, the C++ compiler is required to issue a diagnostic since pointer decay is not permitted to occur in this particular instance, and delete requires a pointer type.
The behaviour on attempting to call free on automatic memory is undefined.
You only need to free what was malloced.
Your ptr is not a pointer, it is an array; an automatic local (inside main()) variable. It does not need freeing and attempting to free it is a mistake.
All the static Strings will be allocated in the data section. You can't free data from this section. Threrefore, you can free only data the you have allocated with malloc (calloc / ralloc)
in C programming language, you cannot write the instruction you made for obvious reasons. First of all, it must be understood that a pointer variable is a variable like so many others with a type except that it contains only addresses, so it is called a pointer variable because it contains the address of what is in memory. A pointer is therefore an address associated with a type of data and these two elements are inseparable.
If the pointer variable contains the address of an object of the whole type, the pointed object is used to know how to interpret the bits that make up this object, as well as its size. The instruction you wrote is therefore a constant pointer to a character type stored somewhere in memory. The string is therefore probably placed in a read-only data segment and therefore you cannot modify the string or release its memory, because the pointer variable does not point to a string in a space allocated dynamically beforehand by the "malloc" or "calloc" allocation function, and that is why you have the error message.
The second error is due to a confusion of your part here too, you must understand that there is a difference between an array of characters and a pointer. In simpler terms, a pointer variable is not an array and an array is not a pointer, but access to the element is done in the same way. For an array, the characters that make up the string and end with "\0" can be changed, but the array of characters will always point to the same address in memory and the pointer can contain another address, but beware, if you allocate the memory with a pointer and then point to other pars without releasing the memory you allocated creates a memory leak.
This is the proper way of using delete ! you first have to let the compiler know that the variable ptr is dynamic by using new!
#include<iostream>
#include<new>
using namespace std;
int main(void) {
char *ptr;
try{
ptr = new char [20];
} catch(bad_alloc xa){
cout<<"error";
}
ptr= "Hello World";
cout<<ptr;
delete [] ptr;
}

Returning an address of a local pointer variable to main() function

In the following example, function func() returning an address of a local pointer variable to main() function. It's working fine in GCC.
So, Is it well-defined behaviour?
#include <stdio.h>
#include <stdlib.h>
int *func(void);
int *func(void)
{
int *p;
p = malloc(sizeof *p);
*p = 10;
return p;
}
int main()
{
int *ptr = func();
printf("%d\n",*ptr);
return 0;
}
No, you do not return a pointer to (address of) a local variable. That would be doing something like
int i = 10;
return &i;
Instead you return a pointer to an object allocated on the heap.
You do have a memory leak though, since you don't free the memory anywhere. Calling free should be done by the code calling your function (unless it in turn return the pointer value, where the responsibility continues upt he call-chain).
Inside func(), p is a pointer to memory allocated by malloc() (or to potentially allocated memory, since malloc() can fail, returning a null pointer; this should be checked for). If successful, this memory allocation will persist until it is explicitly freed.
The value of p is returned to the calling function, main() in this case. p is either a pointer to a successful allocation, or is a null pointer, and the returned value (which is temporary, and not an lvalue) is then assigned to ptr. So, the allocated storage can be accessed through ptr, which is a copy of the value held by p before func() returned, though the lifetime of p itself has ended now that func() has returned.
Of course ptr should be freed when it is no longer needed to avoid memory leaks. And, there is potential undefined behavior here if malloc() fails, since then ptr is a null pointer.
This is perfectly valid.
What is not guaranteed is what will happen to the variables on the stack frame once a function returns and the stack frame shrinks.
What you are returning is an address to some malloced memory and not the address of a local variable (allocated on the stack). This is very similar to how strdup() works. Here's an implementation of strdup() taken from here.
char *
strdup(str)
const char *str;
{
size_t len;
char *copy;
len = strlen(str) + 1;
if (!(copy = malloc((u_int)len)))
return (NULL);
bcopy(str, copy, len);
return (copy);
}
One obvious downside of this (as mentioned by "Some programmer dude") is that the responsibility of freeing is passed on to the caller.
This is a valid and correct code, although bit confusing.
The func is allocating memory of size int. The allocation is done via de-referencing a pointer variable of type int.
Alter allocation the integer value of 10 is set in the memory. 10 should be set as integer (can be compiler dependent). But definitely will not be of greater than the size of integer so should be safe operation.
After that the pointer value is returned by the function.
In main() the returned pointer is set to another integer pointer. This points to the original memory allocated by malloc().
After that the de-referenced integer pointer is printed in the printf() statement. This will print the value of 10.
What is missing is the free() call, which is not the good behaviour in here.
This can be a good academic exercise for kids.

How free memory after of realloc

Is correct ways to free up memory in this code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void ){
char *string1, *string2;
string1 = (char*) malloc(16);
strcpy(string1, "0123456789AB");
string2 = realloc(string1, 8);
printf("string1 Valor: %p [%s]\n", string1, string1);
printf("string2 Valor: %p [%s]\n", string2, string2);
free(string1);
free(string2);
return 0;
}
Since the two pointers point to the same direction
I think your confusion comes from the (uninspired) expression "free pointers" (you used in your post, but edited it out since). You don't free pointers. You free memory. The pointer is just telling which memory.
In your example you have: the memory obtained from malloc. string1 points to this memory. Then when you call realloc a new memory block is obtained (possibly starting at the same address, possibly not), but realloc takes care to release the old one if needed (and is therefore undefined behavior to access or free it yourself). string2 points to this new memory block.
So you have to free just the memory block obtained from realloc. string2 points to that memory.
In short, no.
Per the C Standard:
7.22.3.5 The realloc function
...
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.
Once you call realloc(), you do not have to free() the memory addressed by pointer passed to realloc() - you have to free() the memory addressed by the pointer realloc() returns. (Unless realloc() returns NULL, in which case the original block of memory - passed to realloc() - has to be free()'d.)
When you call realloc, either the returned pointer is the same as the original, or a new pointer is returned and the original pointer becomes invalid. In the first case, calling free on both string1 and string2 results in a double-free since the pointers are equal. In the second case, calling free on string1 is a double-free since it was already freed.
So either way you have a double-free which results in undefined behavior.
From the man page for realloc:
void *realloc(void *ptr, size_t size);
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range
from the start of the region up to the minimum of the old and new
sizes. If the new size is larger than the old size, the added memory
will not be initialized. If ptr is NULL, then the call is equivalent
to malloc(size), for all values of size; if size is equal to zero, and
ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr
is NULL, it must have been returned by an earlier call to malloc(),
calloc() or realloc(). If the area pointed to was moved, a free(ptr)
is done.
The realloc() function returns a pointer to the newly allocated
memory, which is suitably aligned for any kind of variable and may be
different from ptr, or NULL if the request fails.
Also from the man page for free:
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(). Otherwise, or if free(ptr) has already been called before,
undefined behavior occurs. If ptr is NULL, no operation is performed.
You only need to free(string2).
Short answer: in your code, calling free(string2) is correct, and sufficient. Calling free(string1) is incorrect.
When you called realloc (and assuming that the call succeeded), its return value (which you stored in string2) became the one and only way to refer to the one block of memory that you have.
It may be that realloc resized your memory block "in place", meaning that the values of string2 and string1 are equal. In that case, calling free(string1) is wrong because you're freeing the same pointer twice.
It may be that realloc moved your data to a new place in the process of resizing it. In that case, the values of string2 and string1 are unequal. But in that case, after it finds a new place for your data and copies it there, realloc automatically frees the old block for you. So, again, calling free(string1) is wrong because you're freeing an already-freed pointer.
Think of realloc as something equivalent to:
void *
realloc(void *old, size_t new_size)
{
size_t old_size = magic_internal_function_that_knows_the_size_of(old);
void *new = malloc(new_size);
if (new == NULL)
return NULL;
memcpy(new, old, new_size > old_size ? old_size : new_size);
free(old);
return new;
}
If you have the magic function that can figure out how big an allocation is from the pointer, you can implement realloc yourself like this. malloc pretty much must have this function internally for free to work.
realloc can also do clever things like figuring out that you're reallocating to a smaller size and just free part of your allocation or figure out that you're growing your allocation and there's enough space after to fit it. But you don't need to think about those cases. Thinking that realloc is malloc+memcpy+free will not mislead you except that you need to remember that realloc failing and returning NULL means it didn't do the free.
The realloc implicity frees the input, it may not do anything at all, but you cannot free it after to re-alloced memory. So
char *string1, *string2;
string1 = (char*) malloc(16);
....
string2 = realloc(string1, 8); // this line implicitly frees string1
free(string1); // this is wrong !!!
free(string2);

Resources