Dynamic memory allocation in C - c

i just experiment the things on the c language
could you answer my question regarding the program i've written
void main()
{
char *p,; // created a pointer pointing to string
p = (char *) malloc(50); // dynamically create 50 bytes.
strcpy(p, "this code is written about the dynamic allocation");
p += 20;
free(p);
}
Now could anyone tell me what is the effect of free(p) statement will the last 30 bytes will be freed of and used for the future memory allocation.? what would be the output?

You are not supposed to free any addresses but those returned by malloc(), calloc() or realloc(). And p + 20 is no such address.
http://codepad.org/FMr3dvnq shows you that such a free() is likely to fail.
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.
Does the pointer passed to free() have to point to beginning of the memory block, or can it point to the interior? is also worth reading.
Even if you could use free() on any pointer that points to a malloc'd memory - your could would free it twice since you are calling free() on more than one memory inside that area. And double-frees are evil as they can result in security holes.

It will result in Undefined Behavior.
The free() function shall cause the space pointed to by ptr to be deallocated; that is, made available for further allocation. If ptr is a null pointer, no action shall occur. Otherwise, if the argument does not match a pointer earlier returned by the calloc(), malloc(), posix_memalign(), realloc(), strdup() function, or if the space has been deallocated by a call to free() or realloc(), the behavior is undefined.

Related

Can I realloc() an unallocated pointer?

Normally, realloc() is used to reallocate a previously allocated pointer:
int *DynamicArray = malloc(sizeof(int)*SomeArbitraryValue);
// Some rando code where DynamicArray is used
DynamicArray = realloc(DynamicArray, sizeof(int)*SomeOtherArbitraryValue)
But can realloc() be used to directly allocate memory? As in
int *DynamicArray = realloc(/*...*/);
Can realloc() handle non-preallocated pointers?
Yes, just pass NULL to it's first argument.
The manpage of realloc(3) says ...
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.
As the answer by #ZhangBoyang tells you, yes, assuming one possible interpretation of your question. However the way you've worded your question ("non-preallocated pointers") suggests you may have misunderstanding of some of the concepts involved. malloc does not "allocate pointers". It allocates objects, and pointers are values that point to objects. The lifetime of those objects are not connected to the lifetime of any particular pointer pointing to them.
Passing a pointer to realloc doesn't "do anything to" the pointer. It does something to the object pointed to by it. If the pointer is uninitialized or invalid, the call has undefined behavior and bad things will happen. If the pointer is a null pointer, however, realloc(ptr, n) will behave exactly as malloc(n).

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);

2 Ways of calling free - is there a difference?

Is there a difference between those two variants of calling free after allocating memory on the heap:
// variant 1
int* p1 = (int*) malloc(sizeof(int)*4);
free(p1);
//variant 2
int* p2 = (int*) malloc(sizeof(int)*4);
free(*p2);
*p2 = NULL;
Yes, there is a difference.
Variant 2 is invalid. free expects a pointer previously returned by malloc, calloc, or realloc. *p2 is the first int in the allocated space, though. As man free says, undefined behavior occurs therefore (quotation adjusted for this specific case):
free() function frees the memory space pointed to by [p1], which must have been returned by a previous call to malloc(), calloc(), or realloc(). Otherwise, [...] undefined behavior occurs.
Notes:
don't cast the result of malloc
Yes. free(*p2) is invalid.
free frees the memory at the address it's given. Consider: what does p1 evaluate to? Its value is the pointer that malloc returned - so p1 evaluates to the pointer to the memory that malloc allocated.
What does *p2 evaluate to? Its value is the integer that is stored at the address of p2. This can be anything and it is very unlikely it'll be a valid pointer. Thus free will attempt to free an invalid memory address and you'll get a segfault if you're lucky.
Yes, there's a difference. The first way, called on a pointer pointing to memory allocated by malloc is right. The second, calling a dereference of such a pointer, attempts to free some arbitrary memory address (with the value held in the value that pointer is pointing to), and is just wrong.
free(p1);
This is valid as you allocate memory to p1 and then free, thus no problem.
free(*p2);
It is unlikely to be valid as *p2 may or may not be a valid pointer (which need to have an allocated memoty ).
using free() on a pointer which is not allcocated memory using malloc or similar will cause error.

C realloc() function fails

Why does this code not work?
char *x=malloc(100);
x++;
x=realloc(x, 200);
I mean x is a valid string pointer, just incremented by one?
See C Standard (C99, 7.20.3.4p3) on realloc and my emphasis:
void *realloc(void *ptr, size_t size);
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.
In your case x was returned by malloc, not x + 1. So your program invokes undefined behavior.
Think about what realloc does. How can it free the pointer at address x+1 when malloc actually created a pointer at address x?
In more concrete terms, let's assume you allocated 100 bytes at address 0x1000. Now x is incremented, pointing at 0x1001. Then you call realloc at the new address. Because none of malloc, calloc, and realloc created 0x1001, free (or equivalent code) used by the call to realloc has no idea how to do anything with 0x1001; it can't even fathom how many bytes of memory it occupies. It only knows about the 100 bytes at 0x1000.
The basic idea behind implementations of malloc and friends is that you keep track of the pointers assigned and how many bytes were allocated. Then when free is called later, the pointer passed to free is looked up. If there is no reference to that pointer passed to free, what else is there to do except crash? That, to me, is more logical than supposing you can keep using a pointer that may or may not be valid.
char *x=malloc(100);
x++;
x=realloc(x, 200);
In the code shown above the address pointed by the pointer x is changed before invoking the realloc() function. This is undefined behavior in C.
This is an undefined behavior as you if you think that you have obtained a pointer from malloc() which is wrong.
Clearly x was returned by malloc and its value was changed before calling realloc() Hence it is showing the undefined behavior.

What does "pointer being freed was not allocated" mean exactly?

I have trouble with a program where im trying to copy a string to a structs string variable in c. After copying the string im trying to free the temporary string variable which is copied to the structs string variable. But when i try to free the string the program turns on me and says that "pointer being freed was not allocated". I don't understand exactly what is going on.
char str[]=" "; //temporary string to copy to structs string
str[3]=s; //putting a char s in middle
strcpy(matrix[i-1][j].c, str); //copying the string
free(str); //freeing str that now is useless when copied
Only pointers returned by calls to malloc(), realloc() or calloc() can be passed to free() (dynamically allocated memory on the heap). From section 7.20.3.2 The free function of C99 standard:
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument 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 free or realloc,
the behavior is undefined.
In the posted code, str is not dynamically allocated but is allocated on the stack and is automatically released when it goes out of scope and does not need to be free()d.
Be careful. This code shows confusion about two things:
The difference between stack and heap memory
The operation of strcpy
Point 1
This has already been answered in a way, but I'll expand a little:
The heap is where dynamic memory is given to your process. When you call malloc (and related functions), memory is returned on the heap. You must free this memory when you are done with it.
The stack is part of your process's running state. It is where ordinary variables are stored. When you call a function, its variables are pushed onto the stack and popped back off automatically when the function exits. Your str variable is an example of something that is on the stack.
Point 2
I'd like to know what that c member of your matrix array is. If it is a pointer, then you might be confused about what strcpy does. The function only copies bytes of a string from one part of memory to another. So the memory has to be available.
If c is a char array (with sufficient number of elements to hold the string), this is okay. But if c is a pointer, you must have allocated memory for it already if you want to use strcpy. There is an alternative function strdup which allocates enough memory for a string, copies it, and returns a pointer. You are responsible for freeing that pointer when you no longer need it.
It used free without using malloc. You can't release memory that hasn't been allocated.
Your code doesn't allocate any memory for the string. It simply copies a string from one string to the memory used by another (a string of spaces).
Memory is allocated using functions like malloc(), realloc(), etc. and then freed with free(). Since this memory was not allocated that way, passing the address to free() results in the error.
You did not use malloc() to allocate space in the heap for str. Therefore, str is allocated on the stack and cannot be deallocated with free(), but will be deallocated when str goes out of scope, i.e. after the function containing the declaration returns.

Resources