c realloc, what does size really mean - c

Could someone explain what second parameter in realloc really is as I cant find a way to test it.
So suppose that we have something like this
int *p = malloc(sizeof(int)); //we have just enough space to store single int value
now if I want to store 2 int values in p do I need to send to realloc as second parameter 2 * sizeof(int) new size of the block or sizeof(int) as it needs to extend memory for size of int
In case I should send to realloc total value of new block in this case 2 * sizeof(int), what will it do in case I send it just sizeof(int), just return original pointer and do nothing within memory or something else?

The second parameter is the new size of the memory block (total new size) in bytes. If you want room for 2 ints, you'd use 2 * sizeof(int).
just return original pointer and do nothing within memory or something else?
This is not guaranteed by the specifications. Many implementations will just return the original pointer unchanged, but they could just as easily move it. You will not get a new memory allocation large enough for 2 ints, however, merely the original data values in a memory location large enough for sizeof(int).

You want to tell realloc the new total size of the allocation. So from your example, 2 * sizeof(int).
Your second question isn't entirely clear, so I'll try to wrap all those pieces into one sentence. If you call realloc with the same size value as the original call to malloc, it is up to the implementation whether to return the original pointer or to move the data to a (implementation-defined) more convenient place; if you then try to store two ints in the space for which you only requested one int then you've triggered undefined behavior. It could clobber other allocated memory (causing wrong results in calculations) or (more likely) it could clobber malloc's own bookkeeping data (likely your program will abort with a Segfault somewhat later on when malloc actually takes a look at the data.

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.

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.

Move pointer and realloc, C

I'm trying to code a buffer for an input file. The Buffer should always contain a defined amount of data. If a few bytes of the data were used, the buffer should read data from the file until it has the defined size again.
const int bufsize = 10;
int *field = malloc(bufsize*sizeof(int)); //allocate the amount of memory the buffer should contain
for(i=0;i<bufsize;++i) //initialize memory with something
*(field+i) = i*2;
field += 4; //Move pointer 4 units because the first 4 units were used and are no longer needed
field= realloc(field,bufsize*sizeof(int)); //resize the now smaller buffer to its original size
//...some more code were the new memory (field[6]-field[9]) are filled again...
Here is a short example of how I'm trying to do it at the moment (without files, because this is the part thats not working), but the realloc() always returns NULL. In this example, the first 4 units were used, so the pointer should move forward and the missing data at the end of the memory (so that it will again contain 10 elements) should be allocated. What am I doing wrong?
I would be very thankful if someone could help me
You need memmove() instead
memmove(field, field + 4, (bufsize - 4) * sizeof(*field));
you don't need to realloc() because you are not changing the size of the buffer, just think about it.
If you do this
field += 4;
now you lost the reference to the begining of field so you can't even call free on it, nor realloc() of course. Read WhozCraig comment for instance.
Doing realloc() for the same size doesn't make that much sense.
Using realloc() the way you do causes some other problems, for instance when it fails you also run into the same problem, you loose reference to the original pointer.
So the recommended method is
void *pointer;
pointer = realloc(oldPointer, oldSize + nonZeroNewSize);
if (pointer == NULL)
handleFailure_PerhapsFree_oldPointer();
oldPointer = pointer;
So the title of your question contains the answer to it, what you need is to move the data from offset 4 * sizeof(int) bytes to the begining of the pointer, for which memmove() is the perfect tool, notice that you could also think of using memcpy() but memcpy() cannot handle the case of overlapping data, which is your case.
Your problem should be named as Cyclic Buffer.
You should call malloc() just once when opening file and once free() when you close it.
You don't need to call realloc() at all. All is necessary is advaning pointer by amount of read data, wrapping its value around size of buffer and replacing old data with new data from file.
Your problem with realloc(): you must pass same pointer to it which was previously returned from malloc() or realloc() without offsetting it!

Realloc simply not diong anything, not erroring

I've got the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
//just checking to see where the stack
printf("The stack is around %p\n", &argc); is, making sure arr isn't in it
char ** arr = malloc(8*sizeof(char*));
printf("arr is size %li, at %p\n", sizeof(arr), arr);
arr = realloc(arr, 100); //I picked a weird number to show it isn't doing anything. I've picked different numbers (like 200, 2*sizeof(char*)*sizeof(arr), and 16)
printf("arr is size %li, at %p\n", sizeof(arr), arr);
}
That's the entirety of the file (it's a unit test; I was noticing it elsewhere)
The output of the above is as follows:
The stack is around 0x7fff5b94d12c
arr is size 8, at 0x120f010
arr is size 8, at 0x120f010
Perhaps I'm misunderstanding what realloc should do. I'm expecting the following output.
The stack is around 0x7fff5b94d12c
arr is size 8, at 0x120f010
arr is size <size>, at <somewhere>
where <size> is... something odd like 12... at least not 8 and <somewhere> is most likely 0x120f010 but possibly anywhere reasonable.
Are my expectations wrong or am I using realloc incorrectly?
The output of your program is correct, because
Neither malloc nor realloc have anything to do with the automatic storage (i.e. "the stack"). They allocate memory from the dynamic storage area (i.e. "the heap"). One should not expect the position of the top of the stack to change in response to calls to malloc, realloc, or for that matter, any other function.
The value of sizeof(arr) does not depend on what you have allocated to it. It is computed at compile time, and it is always equal to the size of a pointer. On your system, pointers use 8 bytes.
malloc often gives you more memory that you ask, and stores the actual value in a special location that realloc can access at a later time. If you realloc down, or realloc within the bounds, the value returned by realloc does not change. That's the reason why it may perform better than simply calling malloc and memcpy.
sizeof arr
That's the same as
sizeof char**
The size of a pointer isn't going to change, and taking the size of a pointer is not going to tell you how much memory it refers to. Pointers are not arrays, and sizeof is evaluated at compile time.
As for the address bit, realloc doesn't guarantee that the memory block was moved. It could simply expand it successfully and return the same address.
Also, I realize this is just example code, but be aware that, if realloc failed, you leaked what arr originally pointed to.
It's not uncommon, and in fact a bit expected, that a malloc call followed directly by realloc would not change the address of the pointer. In many cases the allocator can just extend the amount of memory reserved at the address and not have to move the pointer. This is what is happening here.
This isn't something you should ever depend on though. It's just a quirk of the implementation
If your assumption is that realloc() has to return a different pointer, then your assumption is wrong.
Typically if you're reducing the size of the allocated memory or leaving it "as is", then realloc() can return the same pointer and avoid copying data, etc.
Sometimes if you're increasing the size of the allocated memory realloc() can check if there's free space above the existing space and still return the same pointer (and avoid copying data).
Mostly, it's only when there is no free space above the allocated memory that realloc() must copy the data somewhere else and return a different pointer.

how is dynamic memory allocation better than array?

int numbers*;
numbers = malloc ( sizeof(int) * 10 );
I want to know how is this dynamic memory allocation, if I can store just 10 int items to the memory block ? I could just use the array and store elemets dynamically using index. Why is the above approach better ?
I am new to C, and this is my 2nd day and I may sound stupid, so please bear with me.
In this case you could replace 10 with a variable that is assigned at run time. That way you can decide how much memory space you need. But with arrays, you have to specify an integer constant during declaration. So you cannot decide whether the user would actually need as many locations as was declared, or even worse , it might not be enough.
With a dynamic allocation like this, you could assign a larger memory location and copy the contents of the first location to the new one to give the impression that the array has grown as needed.
This helps to ensure optimum memory utilization.
The main reason why malloc() is useful is not because the size of the array can be determined at runtime - modern versions of C allow that with normal arrays too. There are two reasons:
Objects allocated with malloc() have flexible lifetimes;
That is, you get runtime control over when to create the object, and when to destroy it. The array allocated with malloc() exists from the time of the malloc() call until the corresponding free() call; in contrast, declared arrays either exist until the function they're declared in exits, or until the program finishes.
malloc() reports failure, allowing the program to handle it in a graceful way.
On a failure to allocate the requested memory, malloc() can return NULL, which allows your program to detect and handle the condition. There is no such mechanism for declared arrays - on a failure to allocate sufficient space, either the program crashes at runtime, or fails to load altogether.
There is a difference with where the memory is allocated. Using the array syntax, the memory is allocated on the stack (assuming you are in a function), while malloc'ed arrays/bytes are allocated on the heap.
/* Allocates 4*1000 bytes on the stack (which might be a bit much depending on your system) */
int a[1000];
/* Allocates 4*1000 bytes on the heap */
int *b = malloc(1000 * sizeof(int))
Stack allocations are fast - and often preferred when:
"Small" amount of memory is required
Pointer to the array is not to be returned from the function
Heap allocations are slower, but has the advantages:
Available heap memory is (normally) >> than available stack memory
You can freely pass the pointer to the allocated bytes around, e.g. returning it from a function -- just remember to free it at some point.
A third option is to use statically initialized arrays if you have some common task, that always requires an array of some max size. Given you can spare the memory statically consumed by the array, you avoid the hit for heap memory allocation, gain the flexibility to pass the pointer around, and avoid having to keep track of ownership of the pointer to ensure the memory is freed.
Edit: If you are using C99 (default with the gnu c compiler i think?), you can do variable-length stack arrays like
int a = 4;
int b[a*a];
In the example you gave
int *numbers;
numbers = malloc ( sizeof(int) * 10 );
there are no explicit benefits. Though, imagine 10 is a value that changes at runtime (e.g. user input), and that you need to return this array from a function. E.g.
int *aFunction(size_t howMany, ...)
{
int *r = malloc(sizeof(int)*howMany);
// do something, fill the array...
return r;
}
The malloc takes room from the heap, while something like
int *aFunction(size_t howMany, ...)
{
int r[howMany];
// do something, fill the array...
// you can't return r unless you make it static, but this is in general
// not good
return somethingElse;
}
would consume the stack that is not so big as the whole heap available.
More complex example exists. E.g. if you have to build a binary tree that grows according to some computation done at runtime, you basically have no other choices but to use dynamic memory allocation.
Array size is defined at compilation time whereas dynamic allocation is done at run time.
Thus, in your case, you can use your pointer as an array : numbers[5] is valid.
If you don't know the size of your array when writing the program, using runtime allocation is not a choice. Otherwise, you're free to use an array, it might be simpler (less risk to forget to free memory for example)
Example:
to store a 3-D position, you might want to use an array as it's alwaays 3 coordinates
to create a sieve to calculate prime numbers, you might want to use a parameter to give the max value and thus use dynamic allocation to create the memory area
Array is used to allocate memory statically and in one go.
To allocate memory dynamically malloc is required.
e.g. int numbers[10];
This will allocate memory statically and it will be contiguous memory.
If you are not aware of the count of the numbers then use variable like count.
int count;
int *numbers;
scanf("%d", count);
numbers = malloc ( sizeof(int) * count );
This is not possible in case of arrays.
Dynamic does not refer to the access. Dynamic is the size of malloc. If you just use a constant number, e.g. like 10 in your example, it is nothing better than an array. The advantage is when you dont know in advance how big it must be, e.g. because the user can enter at runtime the size. Then you can allocate with a variable, e.g. like malloc(sizeof(int) * userEnteredNumber). This is not possible with array, as you have to know there at compile time the (maximum) size.

Resources