i have problem with C, this code throw stack dump. I don't have idea whats wrong.
char *text;
text = (char *) malloc(sizeof (char));
int size = 1;
char c = 'a';
char *new;
while (1) {
c = getchar();
putchar(c);
if (c == 10) {
text[size - 1] = '\0';
break;
}
text[size - 1] = c;
size++;
new = (char *) realloc(text, size * sizeof (*new));
free(text);
text = new;
}
In your code, you pass text as the first argument to realloc() and later, without checking for failure, you pass the same to free(). That is what is causing the issue here.
As per C11, chapter §7.22.3.5
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. [...] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
So, if the realloc() is success, afterwards, calling
free(text);
invokes undefined behavior. You need not to bother about text anymore, remove the call to free().
Related, for free(), §7.22.3.3
[...] Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
TL;DR First check for the success of realloc(), if success, don't touch text, if realloc() fails, then you need to call free(text);
You shouldn't free the pointer text because upon success realloc() deallocates the old pointer.
From C11 standard chapter 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.
Related
How does realloc() reallocate the memory which was first allocated by malloc()?
I know that you need to use malloc() before you´re able to reallocate the memory, but I don´t understand how that really should work. What if a dynamic-memory object gets decreased in size by realloc()? Is this respective piece of the object just erased after the call to realloc()?
My Question is:
How does the realloc() function reallocate a dynamic-memory object created by malloc()?
Note: I did this Q&A because many beginners seem to be still confused about the issue of reallocating memory using realloc() despite already existing questions here on SO for that topic. They seem to be a little confusing for anyone who is new to the topic and still do not represent the whole behavior of realloc(). Therefore, and because the questions, IMHO, still do not quite fit the answer I´d want to give, I made my own Q&A.
Note: All citations in the following answer are quoted from the actual C standard, ISO/IEC 9899:2018 (C18), section 7.22.3.4.
First, the synopsis for the realloc() function from ISO/IEC 9899:2018, Section 7.22.3:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Despite its name, the realloc() function does not "reallocate" anything. realloc() is not modifying an extant object in memory. Instead, it does some sort of "create (new object) & copy the data" routine.
If size is not 0 and ptr either points to an object that was allocated by one of the memory management functions (not just malloc() only) or points to NULL, then realloc() usually creates a new object and copies the data from the old object into the new object.
*I do say usually because you can´t assume that a new object in memory is really allocated. You must always check whether or not it was allocated by checking whether the returned pointer points to NULL.
If the size of the new object is larger than the old object, the bytes of the new object that are beyond the size of the old object have indeterminate values. If the new object is shorter than the old object, the values inside the difference between are thrown away. Every other value remains in the new object as it was in the old one.
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.
After that, if:
ptr is not a pointer to NULL and is a pointer earlier returned by a memory management function, and the object this pointer is pointing to has not been deallocated before the call to realloc(),
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.
size is not 0,
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
and a new object could really be allocated if realloc() did not return a pointer to NULL,
If size is nonzero and memory for the new object is not allocated, the old object is not deallocated
and really only if all of these premises are fulfilled, realloc() deallocates the memory of the old object and returns a pointer with the address of the new object in memory.
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.
If realloc() returns a pointer to NULL, no new object is created and the old object remains unchanged at its address in memory.
Optionally, to make the "pseudo-reallocating" behavior almost perfect, it is possible that the new object, after the deallocation of the old object is done (if it happens), is allocated back at the same address in memory where the old object was stored.
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 has not been allocated.
In this case, there are logically two data copying processes in realloc(), one time into a buffer object and later back to the place of where the original old object was stored. The buffer object is deallocated after the execution of realloc()is completed.
The pointer of ptr which first is used for pointing to the old object should not be used for the returned pointer. If the call statement to realloc() looks like this:
ptr = realloc(ptr,size);
then you usually have a memory leak if the reallocation fails because you just overwrote the pointer to the old memory with a null pointer. If you don't have another pointer that points to it, you've leaked the memory.
Therefore, it is usually better to use a variant on:
void *new_space = realloc(ptr, new_size);
if (new_space == NULL)
{
/* …handle out of memory condition… */
/* ptr is still valid and points to the previously allocated data */
return; /* Or otherwise do not continue to the following code */
}
ptr = new_space;
size = new_size;
Note that according to what I´ve said above, the address may be the same as before the call to realloc().
To make sure that memory management is really happening that way, we can try this experiment:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t length1 = 4;
size_t length2 = 2;
int *ptr1 = malloc(sizeof(*ptr1) * length1);
if(ptr1 == NULL)
{
printf("The object could not be allocated!\n");
return 1;
}
printf("value (not address) of ptr1 before realloc(): %p\n", (void *)ptr1);
ptr1 = realloc(ptr1,length2);
if(ptr1 == NULL)
{
printf("No new object allocated. Old object remains!\n");
return 1;
}
printf("value (not address) of ptr1 after realloc(): %p\n", (void *)ptr1);
free(ptr1);
return 0;
}
At my try it gave the output of:
value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
So, the address stored in ptr1 after the use of realloc() is equivalent to before the call of it.
Additional Notes:
realloc() acts as malloc() when ptr is a NULL pointer:
int *ptr = NULL;
size_t length = 4;
ptr = realloc(ptr,sizeof(*ptr) * length);
shall have the same effect as,
int *ptr;
size_t length = 4;
ptr = malloc(sizeof(*ptr) * length);
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
But, in my personal opinion, you should not first allocate dynamic storage by the use of realloc(). I recommend that you always use malloc() or another allocating memory management function instead. It may cause some difficulties to future readers.
You should not use realloc(ptr,0) as substitution for free(ptr) to deallocate the dynamic memory because it is implementation-defined whether the old object is really deallocated or not.
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
Always use free() to deallocate a dynamically allocated object.
I read about dynamic memory allocation in C using this reference.
That document Say's :
realloc() should only be used for dynamically allocated memory. If the
memory is not dynamically allocated, then behavior is undefined.
If we use realloc() something like this:
int main()
{
int *ptr;
int *ptr_new = (int *)realloc(ptr, sizeof(int));
return 0;
}
According to that reference, this program is undefined because pointer ptr not allocated dynamically.
But, If I use something like:
int main()
{
int *ptr = NULL;
int *ptr_new = (int *)realloc(ptr, sizeof(int));
return 0;
}
Is it also undefined behavior according to that reference?
I thing second case does not invoked undefined behaviour. Am I right?
The first case has undefined behavior, and the second doesn't. In the first case, the value of ptr is indeterminate. So passing that value to realloc or any function, is undefined by itself.
On the other hand, since realloc has well defined behavior when passed a null pointer value (it's just like calling malloc)1, the second piece of code is perfectly legitimate (other than the fact you don't free anything).
1 7.22.3.5 The realloc function / p3
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
In the first case the program almost sure will finish by segmentation fault as the linked lists that are created in the heap to find segments are not coherent, in the second case you call the realloc with the NULL first parameter, which means, is a call equivalent to malloc(size)
man realloc says:
void *malloc(size_t size);
void *realloc(void *ptr, size_t size);
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size
The only authorative reference is the standard document. n1570 (the latest C11 standard) has the following to say:
§7.22.3.5 The realloc function, p3:
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. [...]
So, your second example is well-defined.
The first case is obviously undefined behavior because we don't know where the ptr is pointing or what the ptr is holding at that time. And c standard says that 7.20.3.4.2 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.
So first case is Undefined behavior.
In second case compiler knows what ptr has so it is valid but realloc()
will act as malloc() according to 7.20.3.4.3 The realloc function
If ptr is a null pointer, the realloc function behaves like the
malloc function for the specified size.
I'm having some trouble reading a like from user using malloc and getchar. I get the result, however, I get memory leaks using valgrind. I am pretty clueless in this and have asked my classmates and mentors, but none seem to find out why.
char *ReadLineFile(FILE *infile){
int i=0;
char c;
char *newStringLine;
newStringLine = (char *) malloc(sizeof(char));
while( (c = fgetc(infile)) != '\n' ){
newStringLine[i++] = c;
realloc(newStringLine, (sizeof(char) * (i+1)));
}
newStringLine[i] = '\0';
return newStringLine;
}
Valgrind gives me several errors, including Invalid write/read of 1, and invalid realloc.
Your usage of realloc() is erroneous.
realloc(), if successful, frees the passed pointer and returns a new pointer with the allocated memory. You need to
catch the return value of realloc() in a temporary pointer,
check against NULL to ensure success and then
If returned pointer is not NULL, i.e., reallocation is successful, use the new pointer.
If the returned pointer is NULL, make some decisions and you can keep using the old pointer (passed as argument).
Related, quoting C11, chapter §7.22.3.5
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. [....]
and,
[...] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Otherwise, in case, realloc() is successful, you are (most probably) trying to use an already free-d memory, which , of course, causes undefined behavior.
Uh-oh, and did I mention, please see this discussion on why not to cast the return value of malloc() and family in C?
Why allocating a 0 size char block works in this case? But if I write char *string = NULL; it won't work.
I'm using Visual Studio.
int main()
{
char *string = (char *)malloc(0);
string[0] = 'a';
string[1] = 'b';
string[2] = 'c';
string[3] = 'd';
string[4] = '\0';
printf("%s\n",string);
return 0;
}
First let me state, as per the man page of malloc()
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
a call like malloc(0) is valid itself, but then, we need to check the validity of the returned pointer. It can either
Return NULL
Return a pointer which can be passed to free().
but anyways, dereferencing that pointer is not allowed. It will cause out-of-bound memory access and cause undefined behaviour.
That said, two important things to mention,
Please see why not to cast the return value of malloc() and family in C.
Please check the return value of malloc() before using the returned pointer.
So, to answer your question,
Difference between initializing a string with (char *)malloc(0) and NULL
Do not use malloc(0) in this case, as a NULL check on the pointer may fail, giving the wrong impression of a valid allocation of the memory to the pointer. Always use NULL for initialization.
The above code invokes undefined behavior. You have allocated insufficient memory and you are accessing invalid addresses.
According to the specifications, malloc(0) will return either "a null pointer or a unique pointer that can be successfully passed to free()".
malloc definition:
Allocates a block of size bytes of memory, returning a pointer to the
beginning of the block.
The content of the newly allocated block of memory is not initialized,
remaining with indeterminate values.
If size is zero, the return value depends on the particular library
implementation (it may or may not be a null pointer), but the returned
pointer shall not be dereferenced.
Taken from here and found this related question.
If I allocate memory to pointers in a loop successively, does the compiler consider it as a single instance? Concretely:
for (i = 0; i < SOME_VAL; i++)
{
char *p = NULL;
p = malloc(sizeof(char));
SEND_POINTER_ON_NETWORK(p);
}
Will the compiler at every execution create a new instance of p or will it continue allocating memory to p? I am using VS2010.
char *p = NULL;
p = malloc(sizeof(char));
Each call to malloc() within the loop allocates new memory location to the pointer p , if you are trying to extend the already allocated memory to p then use realloc().
The memory management system looks for a free memory slot at the size of the argument in malloc (in this case sizeof(char)). You do not free the memory from one iteration to the next. Therefore, the memory management system 'sees' the memory as occupied and allocates a new memory slot to pointer p.
You have a memory leak in your code.
From ISO/IEC 9899:
(known as c99 standard)
7.20.3.3 The malloc function
Synopsis
1 #include <stdlib.h>
void *malloc(size_t size);
Description
2 The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
The behaving you expect would be made by realloc, which is described as follows:
7.20.3.4 The realloc function
Synopsis
1 #include <stdlib.h>
void *realloc(void *ptr, size_t size);
Description
2 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.
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 the
calloc, malloc, or realloc 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
4 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.
Also notable is the fact, that MSVC compiler isn't strict conform to the standard in all topics.
But in the both cited cases I know they are conform with it. So it is also valid for your question.