How to realloc() in the middle of an array? - c

I have an array of pointers
char *wordlist[9];
and then I malloc() a block of memory on every of this pointers
for(int i=0; i<9; i++)
wordList[i] = (char*)malloc(someLength);
Lets suppose that every time the someLength is different.
And the problem is now, that I want to realloc() ie. 4th elemet of wordList to a larger size than it is now.
wordList[3] = (char*) realloc(&wordList[3], someBiggerSize);
Since malloc allocates a consistent block of memory, is that operation even possible without colliding with wordList[4]?

There's nothing to worry about this in principle. You just have an array of pointers and each element of the array points to a distinct memory block. Each element of the array, each pointer, can be therefore be reallocated independent of the other elements.
Now, I say in principle because your code does have an error. You should pass wordList[3] rather than &wordList[3] to the realloc.

Just remove the & . wordList[3] = (char*) realloc(wordList[3], someBiggerSize);
wordList[3] is a pointer, and realloc expected to get a pointer that allocated by malloc. not pointer to it.
About your last question: every time you call malloc, it return a consistent block of memory. there is not guarantee that memory, allocated by two calls for malloc, will be consistent. In other words, wordList[3] and wordList[4] are not must be consistent, and you can do whatever you want two one of them (as long as you care about the buffers size) without thinking about the other.

Why should it be colliding? You have declared an array of pointers, each of which points to memory that is allocated elsewhere. When you reallocate you are just changing the size/position of this memory, the pointer returned by realloc is as big as it was.
By the way, you shouldn't be using realloc that way, since, if it fails, you'd be leaking memory; see e.g. here.
---edit---
And, as #asaelr noted, you should remove that &, just reallocing the block pointed by wordList[3], not the memory of wordList.

You have a misunderstanding about what realloc does. It will return a whole new block of memory (if the new size is larger than the old size) instead of increasing the size of the block that was passed into it.

malloc allocates a trunk of memory from heap and that trunk of memory can't be allocated for other malloc until you free them. In other words, malloc succeeds only if there are enough continuous free space in the heap. So this makes sure that the memory allocated would not collide with any others in your words.

Each of your pointers points to a separate and independent block of memory. Inside your array of pointers, each element is simply an address and overwriting one won't affect the others. So, what you are doing is fine and won't cause any problems with other elements of the array. As others mentioned, you should be passing wordList[3] and not &wordList[3]

Related

How does C's realloc differentiate between an array of ints and a single int?

Since arrays are just contiguous data of the same type, and you don't need to explicitly put [] somewhere (e.g. you can int *p1 = malloc(sizeof(int) * 4);, how is it that when you realloc(p1, ...), it knows to move (if it has to move) exactly 4 ints worth of space, even if potentially there are other ints in memory?
To clarify the question: If you allocate an array in this way, and also just a single, seperate int - does that mean that these 4+1 total ints are never contiguous in memory, or is this "it's an array" information in the memory block somehow (e.g. they have some sort of delimiter?), or does the compiler infer and remember that from the malloc parameter? Or something else?
Basically, how does it ensure it moves only and exactly those 4, even when there are other blocks of memory of the same size that might be also contiguous?
realloc is defined only when passed a pointer to memory allocated by a member of the malloc family of routines (or a null pointer). These routines keep records of the memory they have allocated. When you call realloc, it uses these records to know how long the allocated block is.
Often, the primary record for a block of memory is put into the bytes just before that block, so all realloc has to do is take the pointer you give it, subtract a known number of bytes from it, and look at the data at that new address, where it will find information about the size of the allocated block. However, other methods are possible too.

Allocating array on heap in C

I'm allocating an array of of "Todo" structs on the heap like so:
struct Todo *todos = malloc(n * sizeof(*todos));
My understanding is that I have now allocated memory for all of my n Todo structs. So if I want to save some values I can just do for example:
todos[i].id = 1;
The problem now is that if I try to free that memory using free(&todos[i]); I get an error telling me that I haven't allocated that pointer.
My question is now, do I just need to free the todos array and not every element on its own?
You have allocated one single block of memory for all your Todo structures. You can not free a single element. Just like you should not free elements of a non-heap allocated array.
Each call to malloc (or calloc) should be matched by a single call to free.
A little bit of background to Some programmer dude's answer
C11 standard, 7.22.3.3 "The free function", paragraph 2:
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 a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
[emphasis by me]
Background (second level...) is that typically, you did not only receive the memory starting at the pointer, but additionally there is some kind of (machine/OS specific) control block right before the pointer's address that is needed to free the memory again.
You might try to peek at this control block by reading some bytes right before the pointer (just out of curiosity), but be aware that this actually is undefined behaviour as well (so don't ever do this in production code!) and might lead to your programme crashing.
As a reference, always that you do:
WhateverTypeInTheWorld *var1 = malloc(whateveryouwanttocompletearray);
then, you have to do
free(var1); /* use the same value you received from malloc() */
to return the memory back... as you did only one malloc(), you can do only one free() and pass to it the same pointer you got from malloc().
When you write:
free(&todos[i].i);
you are passing free the i-esim element field i's address, and not the pointer you received from malloc(). Probably you understood that you can free part of the memory you received... but it doesn't work that way... you get the memory in chunks, and you have to return it in those same chunks you received from malloc.

C - memset vs free

I am confused on what actually happens in memory when memset is called versus what happens when you call free.
For example I have a pointer A that points to an array of char*'s
char** A = (char**)calloc(5, sizeof(char*));
int i;
for(i=0;i<5;i++)
{
//filling
A[i] = (char*)calloc(30, sizeof(char));
scanf("%s", &A[i]);
}
now I want to reset it my char** pointer and all the elements
it points to be completely empty
memset(A, 0, 5);
or
free(A);
what is the difference?
I am somewhat new to C so please speak in layman's terms thank you
The difference is that memset actually sets the value of a block of memory, while free returns the memory for use by the operating system.
By analogy using physical things, memset(beer, 0, 6) applied to a six-pack of beer would apply the value of '0' to all six members of the array beer, while free(beer) would be the equivalent of giving the six-pack away to a friend.
The memset function sets an area of memory to the requested value. Do note that the size you provide is the number of bytes.
The free function releases the allocated memory so it can't be used anymore. Calling free doesn't usually modify the memory in any way. Using the memory after calling free leads to undefined behavior.
Both approaches are incorrect, but somewhat complementary.
memset will set the content of the buffer to the given value, 0 in your case. This will change the value of the pointers, which will cause you to lose the references to the allocated buffers (in each A[i]).
free(A) will release the buffer pointed by A, but this buffer contains pointers, and each of the buffers that is pointed by them will not be freed.
in short - memset does not free a dynamically allocated buffer, and free does not set it to zero.
A correct approach will be something like that:
for(i=0;i<5;i++)
{
// complementary to
// A[i] = (char*)calloc(30, sizeof(char));
free(A[i]);
}
// complementary to
// char** A = (char**)calloc(5, sizeof(char*));
free(A);
A = NULL; // so no one gets confused...
free deallocates the memory, which means A would still be pointing to the same memory location, which is invalid now.
memset will set the memory currently pointed to by A, to whatever you want.
memset changes the contents at the memory address. It does not alter whether the memory is allocated/deallocated.
free does not change the contents at the memory address. It deallocates the block of memory which makes it available for the program to reclaim and reuse. Therefore any pointers to this block become invalid and trying to access the memory should result in a Segfault ("if you're lucky" as my professor would say).
Use memset when you know you are going to be accessing the data at that address again. Use free when you know that the data will no longer be accessed ever again and that the program may reclaim that memory.
memset() method just replaces the x memory bytes with a given character the allocated memory which is pointed by a pointer *a;
memset(a, 'a', x);
The prototype of memset() method is:
void* memset(void*, unsigned int, int);
memset() behaves like strcpy() but the difference is that memcpy() copied the data as it is (byte), but strcpy copies the formatted string as well (so takes more time than memcpy to execute).
However, free() method just deallocates the memory space and makes it available to get occupied.
While other answers explain the difference, let me add an example when both memset() and free() will need to be used together, in a specific order:
If the malloc'ed memory region was used to store any critical/valuable information that needs to be erased to prevent others from snooping on it (say some security-related stuff like managing a password or some other crypto), you would want to first erase the contents in that memory region and then call free() on it to give away that region's control back to the OS.
Hence, just like free() is the opposite of malloc(), memset(to zero)-then-free() is the opposite of calloc().

Freeing portions of dynamically allocated blocks?

I was curious whether there exists a dynamic memory allocation system that allows the programmer to free part of an allocated block.
For example:
char* a = malloc (40);
//b points to the split second half of the block, or to NULL if it's beyond the end
//a points to a area of 10 bytes
b = partial_free (a+10, /*size*/ 10)
Thoughts on why this is wise/unwise/difficult? Ways to do this?
Seems to me like it could be useful.
Thanks!
=====edit=====
after some research, it seems that the bootmem allocator for the linux kernel allows something similar to this operation with the bootmem_free call. So, I'm curious -- why is it that the bootmem allocator allows this, but ANSI C does not?
No there is no such function which allows parital freeing of memory.
You could however use realloc() to resize memory.
From the c standard:
7.22.3.5 The realloc function
#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.
There is no ready-made function for this, but doing this isn't impossible. Firstly, there is realloc() . realloc takes a pointer to a block of memory and resizes the allocation to the size specified.
Now, if you have allocated some memory:
char * tmp = malloc(2048);
and you intend to deallocate the first, 1 K of memory, you may do:
tmp = realloc(foo, 2048-1024);
However, the problem in this case is that you cannot be certain that tmp will remain unchanged. Since, the function might just deallocate the entire 2K memory and move it elsewhere.
Now I'm not sure about the exact implementation of realloc, but from what I understand, the code:
myptr = malloc( x - y );
actually mallocs a new memory buffer of size x-y, then it copies the bytes that fit using memcpy and finally frees the original allocated memory.
This may create some potential problems. For example, the new reallocated memory may be located at a different address, so any past pointers you may have may become invalidated. Resulting in undefined runtime errors, segmentation faults and general debugging hell. So I would try to avoid resorting to this.
Firstly, I cannot think of any situation where you would be likely to need such a thing (when there exists realloc to increase/decrease the memory as mentioned in the answers).
I would like to add another thing. In whatever implementations I have seen of the malloc subsystem (which I admit is not a lot), malloc and free are implemented to be dependent on something called as the prefix byte(s). So whatever address is returned to you by malloc, internally the malloc subsystem will allocate some additional byte(s) of memory prior to the address returned to you, to store sanity check information which includes number of allocated bytes and possible what allocation policy you use (if your OS supports multiple mem allocation policies) etc. When you say something like free (x bytes), the malloc subsystem goes back to peek back into the prefix byte to sanity check and only if it finds the prefix in place does the free successfully happen. Therefore, it will not allow you to free some number of blocks starting in between.

Instead of just using free() and having the pointer pointing some new block, how to really empty the previously-pointed-at memory block?

I am trying to free dynamically allocated memory using free(), but I found that what it does is to have the argument pointer point to some new location, and leaving the previously-pointed-at location as it was, the memory is not cleared. And if I use malloc again, the pointer may point to this messy block, and it's already filled with garbage, which is really annoying..
I'm kinda new to C and I think delete[] in c++ doesn't have this problem. Any advise?
Thanks
By free the memory is just released from use. It is released from being allocated to you. it is not explicitly cleared. Some old contents might be present at those memory locations.
To avoid this, there are two solutions.
Solution 1:
You will need to do a memset after allocating memory using malloc.
Code Example:
unsigned int len = 20; // len is the length of boo
char* bar = 0;
bar= (char *)malloc(len);
memset(bar, 0, len);
Solution 2:
Or use, calloc() which initiliazes memory to 0 by default.
Code Example:
int *pData = 0;
int i = 10;
pData = (int*) calloc (i,sizeof(int));
I think delete[] in c++ doesn't have this problem.
No
It behaves exactly this same way. Unless you explicitly set the pointer to 0 the delete'd pointer will not be pointing to 0. So do always set the pointer to 0 after you delete it.
When should you use malloc over calloc or vice versa?
Since calloc sets the allocated memory to 0 this may take a little time, so you may probably want to use malloc() if that performance is an issue.(Ofcourse One most profile their usage to see if this really is a problem)
If initializing the memory is more important, use calloc() as it does that explicitly for you.
Also, some OS like Linux have an Lazy Allocation memory model wherein the returned memory address is a virtual address and the actual allocation only happens at run-time. The OS assumes that it will be able to provide this allocation at Run-Time.
The memory allocated by malloc is not backed by real memory until the program actually touches it.
While, since calloc initializes the memory to 0 you can be assured that the OS has already backed the allocation with actual RAM (or swap).
How about realloc?
Yes, similar behavior to malloc.
Excerpt From the documentation:
void * realloc ( void * ptr, size_t size );
Reallocate memory block
The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding or reducing the amount of memory available in the block.
The function may move the memory block to a new location, in which case the new location is returned. The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved.If the new size is larger, the value of the newly allocated portion is indeterminate.
In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.
In case that the size is 0, the memory previously allocated in ptr is deallocated as if a call to free was made, and a NULL pointer is returned.
You can use calloc( ) instead of malloc( ) to clear the allocated memory to zero.
Why is having newly allocated memory filled with garbage "really annoying"? If you allocate memory, presumably it's because you're going to use it for something -- which means you have to store some meaningful value into it before attempting to read it. In most cases, in well-written code, there's no reason to care what's in newly allocated memory.
If you happen to have a requirement for a newly allocated block of memory you can call memset after calling malloc, or you can use calloc instead of malloc. But consider carefully whether there's any real advantage in doing so. If you're actually going to use those all-bits-zero values (i.e., if all-bits-zero happens to be the "meaningful value" I mentioned above), go ahead and clear the block. (But keep in mind that the language doesn't guarantee that either a null pointer or a floating-point 0.0 is represented as all-bits-zero, though it is in most implementations they are.)
And free() doesn't "have the argument pointer point to some new location". free(ptr) causes the memory pointed to by ptr to be made available for future allocation. It doesn't change the contents of the pointer object ptr itself (though the address stored in ptr does become invalid).

Resources