Is it safe to use realloc? - c

Some time ago a friend of mine told me not to use realloc because it's unsafe, but he couldn't tell me why, so I made some research on the subject and the nearest references to my doubt were:
First
Second
I want to know if I can continue to use realloc in my code or if it's unsafe is there any other way to reallocate memory?

It's perfectly safe to use realloc. It is the way to reallocate memory in a C program.
However you should always check the return value for an error condition. Don't fall into this common trap:
p = realloc(p, new_size); // don't do this!
If this fails, realloc returns NULL and you have lost access to p. Instead do this:
new_p = realloc(p, new_size);
if (new_p == NULL)
...handle error
p = new_p;

The first of the two linked article raises two complaints above and beyond the "check the call succeeded" points already raised here.
When this is done, the old contents are discarded and left in memory somewhere. For secure memory applications where it is important to erase all traces of data, this behavior is inappropriate.
This is a valid point if you happen to be storing sensitive data (e.g. private keys, unhashed(!) passwords etc.) and want to make it harder for exploits to recover the data or other processes on the system to steal the data.
Since it moves memory around, any old pointers to that memory become invalid and could cause the program to crash or otherwise misbehave.
This point seems like nonsense to me. Their proposed solution is no better, they malloc(), copy and then free() the original which has the same net effect - the address has changed. If you wanted to avoid moving the memory you might be able to use some platform specific calls to do that, if you arranged for there to be sufficient free address space near them. If you knew a priori how much address space to reserve then you'd probably not be thinking of calling realloc() in the first place though!
If you're gambling on realloc() never moving, always growing then you've probably got bigger problems to worry about anyway and switching to malloc() + copy + free() can't possibly solve that.
Besides the "check your return value properly point", the most interesting point from the second article is a warning about:
Do not realloc your buffer by 1 byte at a time.
they warn:
This is guaranteed to churn your memory heap
This is a potentially valid point, but it's not a criticism of realloc() itself; the same would happen if you used malloc()+copy+free(). The real fix is to grow buffers sensibly regardless of how you grow them or better yet allocate in correct sized chunks up front.
They also have a point about
Using realloc to return memory to the system.
They're correct here in that using any size other than 0 might not actually make a return. It probably makes things no worse, but this usage still seems like an example of premature "optimisation". The fix again is to use sensible sized allocations to begin with.
Sort answer: it's not unsafe, but it's not a magical solution to all your problems either.

realloc is safe in itself, but using it safely is a bit tricky -- to the point that I'd say roughly 85-90% of the code I've seen that uses it does not do so safely. The problem is that realloc returns NULL to indicate failure -- but when it does so, the pointer you supplied as input is still valid (provided you didn't resize its allocation to 0).
Therefore, you have to assign the return from realloc to the pointer you supplied as input if and only if realloc returned a non-null pointer. If it returns a null pointer, your previous pointer is valid, but the allocation has not be resized.
Also note that many people assume realloc can only fail and/or move the allocation when you enlarge the allocation. In reality, it can fail (though that's unlikely) or move the data to a different location (much more likely) even when you're reducing the allocation size.

Like everything in C, as long as you know what do you do, it's fine.
(Knowing what do you do includes checking for errors, don't use the old pointer,etc)

Related

Why i have to assign NULL to pointer after freeing allocated memory? [duplicate]

In my company there is a coding rule that says, after freeing any memory, reset the variable to NULL. For example ...
void some_func ()
{
int *nPtr;
nPtr = malloc (100);
free (nPtr);
nPtr = NULL;
return;
}
I feel that, in cases like the code shown above, setting to NULL does not have any meaning. Or am I missing something?
If there is no meaning in such cases, I am going to take it up with the "quality team" to remove this coding rule. Please advice.
Setting unused pointers to NULL is a defensive style, protecting against dangling pointer bugs. If a dangling pointer is accessed after it is freed, you may read or overwrite random memory. If a null pointer is accessed, you get an immediate crash on most systems, telling you right away what the error is.
For local variables, it may be a little bit pointless if it is "obvious" that the pointer isn't accessed anymore after being freed, so this style is more appropriate for member data and global variables. Even for local variables, it may be a good approach if the function continues after the memory is released.
To complete the style, you should also initialize pointers to NULL before they get assigned a true pointer value.
Most of the responses have focused on preventing a double free, but setting the pointer to NULL has another benefit. Once you free a pointer, that memory is available to be reallocated by another call to malloc. If you still have the original pointer around you might end up with a bug where you attempt to use the pointer after free and corrupt some other variable, and then your program enters an unknown state and all kinds of bad things can happen (crash if you're lucky, data corruption if you're unlucky). If you had set the pointer to NULL after free, any attempt to read/write through that pointer later would result in a segfault, which is generally preferable to random memory corruption.
For both reasons, it can be a good idea to set the pointer to NULL after free(). It's not always necessary, though. For example, if the pointer variable goes out of scope immediately after free(), there's not much reason to set it to NULL.
Setting a pointer to NULL after free is a dubious practice that is often popularized as a "good programming" rule on a patently false premise. It is one of those fake truths that belong to the "sounds right" category but in reality achieve absolutely nothing useful (and sometimes leads to negative consequences).
Allegedly, setting a pointer to NULL after free is supposed to prevent the dreaded "double free" problem when the same pointer value is passed to free more than once. In reality though, in 9 cases out of 10 the real "double free" problem occurs when different pointer objects holding the same pointer value are used as arguments for free. Needless to say, setting a pointer to NULL after free achieves absolutely nothing to prevent the problem in such cases.
Of course, it is possible to run into "double free" problem when using the same pointer object as an argument to free. However, in reality situations like that normally indicate a problem with the general logical structure of the code, not a mere accidental "double free". A proper way to deal with the problem in such cases is to review and rethink the structure of the code in order to avoid the situation when the same pointer is passed to free more than once. In such cases setting the pointer to NULL and considering the problem "fixed" is nothing more than an attempt to sweep the problem under the carpet. It simply won't work in general case, because the problem with the code structure will always find another way to manifest itself.
Finally, if your code is specifically designed to rely on the pointer value being NULL or not NULL, it is perfectly fine to set the pointer value to NULL after free. But as a general "good practice" rule (as in "always set your pointer to NULL after free") it is, once again, a well-known and pretty useless fake, often followed by some for purely religious, voodoo-like reasons.
This is considered good practice to avoid overwriting memory. In the above function, it is unnecessary, but oftentimes when it is done it can find application errors.
Try something like this instead:
#if DEBUG_VERSION
void myfree(void **ptr)
{
free(*ptr);
*ptr = NULL;
}
#else
#define myfree(p) do { void ** p_tmp = (p); free(*(p_tmp)); *(p_tmp) = NULL; } while (0)
#endif
The DEBUG_VERSION lets you profile frees in debugging code, but both are functionally the same.
Edit: Added do ... while as suggested below, thanks.
If you reach pointer that has been free()d, it might break or not. That memory might be reallocated to another part of your program and then you get memory corruption,
If you set the pointer to NULL, then if you access it, the program always crashes with a segfault. No more ,,sometimes it works'', no more ,,crashes in unpredictible way''. It's way easier to debug.
Setting the pointer to the free'd memory means that any attempt to access that memory through the pointer will immediately crash, instead of causing undefined behavior. It makes it much easier to determine where things went wrong.
I can see your argument: since nPtr is going out of scope right after nPtr = NULL, there doesn't seem to be a reason to set it to NULL. However, in the case of a struct member or somewhere else where the pointer is not immediately going out of scope, it makes more sense. It's not immediately apparent whether or not that pointer will be used again by code that shouldn't be using it.
It's likely the rule is stated without making a distinction between these two cases, because it's much more difficult to automatically enforce the rule, let alone for the developers to follow it. It doesn't hurt to set pointers to NULL after every free, but it has the potential of pointing out big problems.
the most common bug in c is the double free. Basically you do something like that
free(foobar);
/* lot of code */
free(foobar);
and it end up pretty bad, the OS try to free some already freed memory and generally it segfault. So the good practice is to set to NULL, so you can make test and check if you really need to free this memory
if(foobar != null){
free(foobar);
}
also to be noted that free(NULL) won't do anything so you don't have to write the if statement. I am not really an OS guru but I am pretty even now most OSes would crash on double free.
That's also a main reason why all languages with garbage collection (Java, dotnet) was so proud of not having this problem and also not having to leave to developers the memory management as a whole.
The idea behind this, is to stop accidental reuse of the freed pointer.
Recently I come across the same question after I was looking for the answer. I reached this conclusion:
It is best practice, and one must follow this to make it portable on all (embedded) systems.
free() is a library function, which varies as one changes the platform, so you should not expect that after passing pointer to this function and after freeing memory, this pointer will be set to NULL. This may not be the case for some library implemented for the platform.
so always go for
free(ptr);
ptr = NULL;
This (can) actually be important. Although you free the memory, a later part of the program could allocate something new that happens to land in the space. Your old pointer would now point to a valid chunk of memory. It is then possible that someone would use the pointer, resulting in invalid program state.
If you NULL out the pointer, then any attempt to use it is going to dereference 0x0 and crash right there, which is easy to debug. Random pointers pointing to random memory is hard to debug. It's obviously not necessary but then that's why it's in a best practices document.
From the ANSI C standard:
void free(void *ptr);
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.
"the undefined behavior" is almost always a program crash. So as to avoid this it is safe to reset the pointer to NULL. free() itself cannot do this as it is passed only a pointer, not a pointer to a pointer. You can also write a safer version of free() that NULLs the pointer:
void safe_free(void** ptr)
{
free(*ptr);
*ptr = NULL;
}
I find this to be little help as in my experience when people access a freed memory allocation it's almost always because they have another pointer to it somewhere. And then it conflicts with another personal coding standard which is "Avoid useless clutter", so I don't do it as I think it rarely helps and makes the code slightly less readable.
However - I won't set the variable to null if the pointer isn't supposed to be used again, but often the higher level design gives me a reason to set it to null anyway. For example if the pointer is a member of a class and I've deleted what it points to then the "contract" if you like of the class is that that member will point to something valid at any time so it must be set to null for that reason. A small distinction but I think an important one.
In c++ it's important to always be thinking who owns this data when you allocate some memory (unless you are using smart pointers but even then some thought is required). And this process tends to lead to pointers generally being a member of some class and generally you want a class to be in a valid state at all times, and the easiest way to do that is to set the member variable to NULL to indicate it points to nothing now.
A common pattern is to set all the member pointers to NULL in the constructor and have the destructor call delete on any pointers to data that your design says that class owns. Clearly in this case you have to set the pointer to NULL when you delete something to indicate that you don't own any data before.
So to summarise, yes i often set the pointer to NULL after deleting something, but it's as part of a larger design and thoughts on who owns the data rather than due to blindly following a coding standard rule. I wouldn't do so in your example as I think there is no benefit to doing so and it adds "clutter" which in my experience is just as responsible for bugs and bad code as this kind of thing.
It is always advisable to declare a pointer variable with NULL such as,
int *ptr = NULL;
Let's say, ptr is pointing to 0x1000 memory address.
After using free(ptr), it's always advisable to nullify the pointer variable by declaring again to NULL.
e.g.:
free(ptr);
ptr = NULL;
If not re-declared to NULL, the pointer variable still keeps on pointing to the same address (0x1000), this pointer variable is called a dangling pointer.
If you define another pointer variable (let's say, q) and dynamically allocate address to the new pointer, there is a chance of taking the same address (0x1000) by new pointer variable. If in case, you use the same pointer (ptr) and update the value at the address pointed by the same pointer (ptr), then the program will end up writing a value to the place where q is pointing (since p and q are pointing to the same address (0x1000)).
e.g.
*ptr = 20; //Points to 0x1000
free(ptr);
int *q = (int *)malloc(sizeof(int) * 2); //Points to 0x1000
*ptr = 30; //Since ptr and q are pointing to the same address, so the value of the address to which q is pointing would also change.
This rule is useful when you're trying to avoid the following scenarios:
1) You have a really long function with complicated logic and memory management and you don't want to accidentally reuse the pointer to deleted memory later in the function.
2) The pointer is a member variable of a class that has fairly complex behavior and you don't want to accidentally reuse the pointer to deleted memory in other functions.
In your scenario, it doesn't make a whole lot of sense, but if the function were to get longer, it might matter.
You may argue that setting it to NULL may actually mask logic errors later on, or in the case where you assume it is valid, you still crash on NULL, so it doesn't matter.
In general, I would advise you to set it to NULL when you think it is a good idea, and not bother when you think it isn't worth it. Focus instead on writing short functions and well designed classes.
This might be more an argument to initialize all pointers to NULL, but something like this can be a very sneaky bug:
void other_func() {
int *p; // forgot to initialize
// some unrelated mallocs and stuff
// ...
if (p) {
*p = 1; // hm...
}
}
void caller() {
some_func();
other_func();
}
p ends up in the same place on the stack as the former nPtr, so it might still contain a seemingly valid pointer. Assigning to *p might overwrite all kinds of unrelated things and lead to ugly bugs. Especially if the compiler initializes local variables with zero in debug mode but doesn't once optimizations are turned on. So the debug builds don't show any signs of the bug while release builds blow up randomly...
Set the pointer that has just been freed to NULL is not mandatory but a good practice. In this way , you can avoid 1) using a freed pointed 2)free it towice
There are two reasons:
Avoid crashes when double-freeing
Written by RageZ in a duplicate question.
The most common bug in c is the double
free. Basically you do something like
that
free(foobar);
/* lot of code */
free(foobar);
and it end up pretty bad, the OS try
to free some already freed memory and
generally it segfault. So the good
practice is to set to NULL, so you
can make test and check if you really
need to free this memory
if(foobar != NULL){
free(foobar);
}
also to be noted that free(NULL)
won't do anything so you don't have to
write the if statement. I am not
really an OS guru but I am pretty even
now most OSes would crash on double
free.
That's also a main reason why all
languages with garbage collection
(Java, dotnet) was so proud of not
having this problem and also not
having to leave to developer the
memory management as a whole.
Avoid using already freed pointers
Written by Martin v. Löwis in a another answer.
Setting unused pointers to NULL is a
defensive style, protecting against
dangling pointer bugs. If a dangling
pointer is accessed after it is freed,
you may read or overwrite random
memory. If a null pointer is accessed,
you get an immediate crash on most
systems, telling you right away what
the error is.
For local variables, it may be a
little bit pointless if it is
"obvious" that the pointer isn't
accessed anymore after being freed, so
this style is more appropriate for
member data and global variables. Even
for local variables, it may be a good
approach if the function continues
after the memory is released.
To complete the style, you should also
initialize pointers to NULL before
they get assigned a true pointer
value.
To add to what other have said, one good method of pointer usage is to always check whether it is a valid pointer or not. Something like:
if(ptr)
ptr->CallSomeMethod();
Explicitly marking the pointer as NULL after freeing it allows for this kind of usage in C/C++.
Settings a pointer to NULL is to protect agains so-called double-free - a situation when free() is called more than once for the same address without reallocating the block at that address.
Double-free leads to undefined behaviour - usually heap corruption or immediately crashing the program. Calling free() for a NULL pointer does nothing and is therefore guaranteed to be safe.
So the best practice unless you now for sure that the pointer leaves scope immediately or very soon after free() is to set that pointer to NULL so that even if free() is called again it is now called for a NULL pointer and undefined behaviour is evaded.
The idea is that if you try to dereference the no-longer-valid pointer after freeing it, you want to fail hard (segfault) rather than silently and mysteriously.
But... be careful. Not all systems cause a segfault if you dereference NULL. On (at least some versions of) AIX, *(int *)0 == 0, and Solaris has optional compatibility with this AIX "feature."
To the original question:
Setting the pointer to NULL directly after freeing the contents is a complete waste of time, provided the code meets all requirements, is fully debugged and will never be modified again. On the other hand, defensively NULLing a pointer that has been freed can be quite useful when someone thoughtlessly adds a new block of code beneath the free(), when the design of the original module isn't correct, and in the case of it-compiles-but-doesn't-do-what-I-want bugs.
In any system, there is an unobtainable goal of making it easiest to the right thing, and the irreducible cost of inaccurate measurements. In C we're offered a set of very sharp, very strong tools, which can create many things in the hands of a skilled worker, and inflict all sorts of metaphoric injuries when handled improperly. Some are hard to understand or use correctly. And people, being naturally risk averse, do irrational things like checking a pointer for NULL value before calling free with it…
The measurement problem is that whenever you attempt to divide good from less good, the more complex the case, the more likely you get an ambiguous measurement. If the goal is do keep only good practices, then some ambiguous ones get tossed out with the actually not good. IF your goal is to eliminate the not good, then the ambiguities may stay with the good. The two goals, keep only good or eliminate clearly bad, would seem to be diametrically opposed, but there is usually a third group that's neither one nor the other, some of both.
Before you make a case with the quality department, try looking through the bug data base to see how often, if ever, invalid pointer values caused problems that had to be written down. If you want to make real difference, identify the most common problem in your production code and propose three ways to prevent it
As you have a quality assurance team in place, let me add a minor point about QA. Some automated QA tools for C will flag assignments to freed pointers as "useless assignment to ptr". For example PC-lint/FlexeLint from Gimpel Software says
tst.c 8 Warning 438: Last value assigned to variable 'nPtr' (defined at line 5) not used
There are ways to selectively suppress messages, so you can still satisfy both QA requirements, should your team decide so.
Long story short: You do not want to accidentally (by mistake) access the address that you have freed. Because, when you free the address, you allow that address in the heap to be allocated to some other application.
However, if you do not set the pointer to NULL, and by mistake try to de-reference the pointer, or change the value of that address; YOU CAN STILL DO IT. BUT NOT SOMETHING THAT YOU WOULD LOGICALLY WANT TO DO.
Why can I still access the memory location that I have freed? Because: You may have free the memory, but the pointer variable still had information about the heap memory address. So, as a defensive strategy, please set it to NULL.

Is it safe to assume that realloc()ing to a smaller size will always succeed? [duplicate]

This question already has answers here:
Can realloc fail (return NULL) when trimming?
(7 answers)
can realloc move pointer if new size smaller?
(6 answers)
Closed 2 years ago.
There is no reason for realloc()ing to a smaller size will fail. It's freeing up the remainder. I see no reason at all for it to fail. This being said, is it safe to assume that realloc()ing to a smaller size will never fail?
"There is no reason for realloc()ing to a smaller size will fail." is an assertion without evidence.
As the spec for the Standard C library does not require a reduction to never fail, robust code would not assume an error is not possible, even if unlikely.
In particular, C17dr spec has Future library directions which discusses reduction to 0.
Invoking realloc with a size argument equal to zero is an obsolescent feature.
I take this to imply now and in the future, the following code which reduces the allocation to 0 should be avoided.
void *p = malloc(42);
...
realloc(p, 0); // Obsolete
// and instead
free(p);
There is no reason for realloc()ing to a smaller size will fail.
Consider an implementation that grabs large blocks from the platform's underlying address space allocator and dices them into small pieces. A realloc that reduces the size of the allocation might require a new block to be allocated if the size requested is not within the range of supported sizes for the large block the block being reallocated came from.
In this case, the implementation will need to get a smaller block from a sub-allocator whose range of serviced sizes includes the size requested. That sub-allocator may not have any free blocks and when it requests a new large block to dice up, that can fail.
So the premise of this question is false.
Also, in general, it is a terrible idea to leap from "I cannot think of any reason this would fail" to "I can assume this will not fail". There are many stories of things that failed for reasons people could not foresee and some of them have horrible consequences.
From the linux manpages:
The realloc() function returns a pointer to the newly allocated memory, which is suitably aligned for any built-in type and may be different from ptr. [...] If realloc() fails, the original block is left untouched; it is not freed or moved.
It cannot be assumed that the block will not be moved because this is implementation-specific. For example, the block could be moved in the case of compactification.
For cases where the requested size is smaller than the original and non-zero, one could safely make a copy of the original pointer before calling realloc, and set the pointer back to that value in case the realloc returns null. If the realloc size is zero, things are a bit murky. Some implementations would treat realloc(ptr, 0); as equivalent to free(ptr); return 0;, which would return null after freeing the object, but others would treat it as equivalent to realloc(ptr,1);, which would only return null in cases where the original pointer would still be valid. Unfortunately, there's no general way of knowing which behavior an implementation would use, and thus no way to properly handle a null return from realloc(ptr, 0);.
TL;DR
No, you cannot assume that.
There is no reason for realloc()ing to a smaller size will fail. It's freeing up the remainder. I see no reason at all for it to fail.
chux covered details about this pretty well. So I answer in a more general way.
The type of reasoning you're using here is a quite dangerous one. Your basic reasoning is "I cannot see why X is true, therefore I assume X is false." Be very careful with reasoning that way.
First, let's skip the very obvious danger that even though you cannot see any reason for realloc failing in this case, that does not mean that you are correct.
Instead let's assume that you are correct. That there is provably no rational reason whatsoever to implement realloc in such a way that it would ever fail is the new size is equal or smaller than the original. Then it's still a faulty argument, because you cannot assume that the programmers who coded the implementation you're using had this knowledge. There was a provably optimal way of doing this, but the coders did not know that.
Also, the very fact that the C standard does NOT say that this is safe is a good indication (however, not a proof) that there are good reasons to not give that guarantee.
If the specifications does not say that it always succeeds during some circumstances, then you should always consider the risk of failure as non-zero. And in this case, the standard does not give any promises, so no you cannot assume that.
Also, in reality there is often the case where it would be relatively easy to implement things in a "good" way, but it will still be more complicated than the simplest way. And sometimes that simplicity is desirable. The easiest way I can think of to implement realloc is something like this:
void *realloc(void *ptr, size_t new_size)
{
void *ret = malloc(new_size);
if(ret) {
memcpy(ret, ptr, new_size);
free(ptr);
}
return ret;
}
One very valid reason of implementing it this way would be that you have a specific environment where you typically never would use realloc and you throw this in for the sole purpose of conforming to the standard. And whenever you do something for the sole purpose of conforming to a standard or specification, you would typically go for simplicity above all else.

Malloc/free own implementation

I'm currently trying to write my own implementation of malloc, and free.
During my research I've found some implementation which request free memoryspace with:
block = sbrk(totalSize);
then there is some other code
and finally they return:
return (block + 1);
But i don't understand why the + 1 is necessary.
Another thing i don't understand why some implementation have a magic number in their struct.
I already searched the web and stackoverflow but didn't find any answers to my question.
So you returned memory from your allocator. All's fine, the user does something with it, and gives your free a pointer. That's it, all you get is an address.
How are you supposed to know from an address alone:
That it was allocated by you to begin with?
That you haven't freed it already?
How big is the memory block it points at?
You must store some meta-data somewhere. The approach illustrated by the examples you described, is to store the meta-data right before the raw memory you give to the caller of malloc. That way, to retrieve it all you have to do is a simple bit of pointer arithmetic with the address you were handed in free.
After that, what meta-data to store is up to you. A magic number is one way to document that the following block was allocated by you. If its bit pattern is sufficiently "distinct" then you'll rarely try to free a block you haven't allocated yourself.
Story Teller has most of the .... story! Pun intended.
Two other points. First an often missed requirement of malloc() is to return aligned memory. malloc() isn't told what it's allocating and so is required to return a block with "the maximum alignment".
If your platform has even alignment (2 byte alignment) where things like int can't start on odd addresses (or just aren't efficient) then +1 might be rounding up. Though it doesn't make much sense to ever return an odd-length block in those circumstances.
Secondly, another smart debug feature is to put some familiar pattern at the end of blocks to check for buffer end overwrites (e.g. out by 1 errors).
I personally think 0xDEADC0D3 is a good block of 4 bytes but that's my sense of humour.

Is there any extra overhead in free that checks for a null pointer?

I am not asking if I need to check to see if a pointer is NULL before calling free, I know I do not. Rather, I am asking whether a (typical) implementation of free sacrifices time to check for a NULL pointer before deallocating, or whether the nature of the process does not actually invoke any additional overhead. For example, someone knowing what free does might imagine that its implementation might be something like this:
void free(void* ptr){
if(ptr != NULL){
<proceed with deallocation>
}
}
But this contradicts the C philosophy of not paying for what I don't use: if I know I will not pass a NULL pointer to free, there should not be a performance deficit as a result. Thus, I am pretty sure that free does not usually invoke such a cost, and in that case I would like to know how/why. I tried searching for the answer to this but I saw a hurricane of questions asking whether deleting a NULL pointer was safe instead.
EDIT: I am already satisfied with the answers and comments, though for future reference I want to make clear what it is I was asking. I was not asking from a programmer's perspective what the state of the program and my NULL pointer are after I call free on it. I was more interested in the perspective of the heap manager. To give an example of what I mean, suppose I am at a bakery and it is my job to take whatever is at the table and dump it all in the trash. It could be 5 brownies, a dozen cookies, or whatever, and yes I know this is not the best analogy but bear with me. I wanted to know if there could exist heap managers that, if for instance, there was "nothing" on the table whether my dumping "nothing" into the trash would make any difference, which would be an implicit handling of "nothing." An explicit handling of "nothing" would be my checking of the table to see if anything is on it before I try to dump it. I wanted to know if heap managers could usually handle the situation implicitly, i.e., by doing the same thing that they would normally do and incidentally also handling a NULL pointer, or explicitly, by making an explicit check to see if a pointer is NULL. As awksp's comment reveals, since it is required that nothing literally be done in the case of a NULL pointer, it must be true that an explicit check exists because treating the NULL pointer the same as the others would not be a no-op, and therefore we must check for NULL explicitly beforehand.
Here's why checking for NULL in free() is more than just a nice idea:
When you use malloc(), you don't have to remember how much memory you asked for: The heap manager does that for you. So, when you free a block, it's got to add the freed block (of the correct size) into whatever data structures it uses to hold this information.
So, how could it know the size? It could find the pointer in some other structure containing lists of all the allocated memory, but without some kind of Content-addressable-memory hardware, that's likely to be slow. So intead, most heap managers use a trick of storing metadata about the block that you were allocated in memory immediately before the pointer they give you. (it can't be
at the end of the block, because remember we don't know the actual block size...)
If the heap manager doesn't explicitly check for NULL, it will start trying to access memory at negative addresses (eg. NULL-16), which is likely to cause access violations and all sorts of other undesirable effects. MUCH better to have a trivial (if x=NULL) before the start.
Does it cause a performance hit? Possibly, but it's totally trivial compared to all the block merging, list searching, etc. that are all needed in typical heap managers.
First - calling free() on a null pointer doesn't really do anything. You don't need to check, you are covered in the case of a zero.
Second - on any modern system, checking a pointer before using it will have tiny overhead, maybe even a single clock cycle, which is literally negligible, so don't hesitate - check when there is need to. Not in the case of free() but there are numerous cases where you'd want to check.
The pointer will have to reach a CPU register before used, so an extra check for null will be very efficient. It is nothing compared to fetching data from ram or thread context switching.
actually what free does is just giving the allocated memory block ( if there is any ) back to your operating system whether it is allocated using malloc or realloc or whatever, there should be a pointer to the start of the block and the length of the block saved somewhere . it has obviously ( in most platforms ) the overhead of 8 byte for each byte allocated , which is a great overhead ( in terms of memory usage ) but it is what operating systems does in reality .
so talking about ANSII C when there is a null pointer passed to the free function according to what said above will do nothing because it points to no block of memory , so as long as it does nothing underneath the hood it will produce a time overhead .
the malloc and free implementations are always one of the biggest problems for who developing operating systems . so i will suggest to implement them once for yourself then try if you can reduce the overheads as much as possible .

Determining realloc() behaviour before calling it

As I understand it, when asked to reserve a larger block of memory, the realloc() function will do one of three different things:
if free contiguous block exists
grow current block
else if sufficient memory
allocate new memory
copy old memory to new
free old memory
else
return null
Growing the current block is a very cheap operation, so this is behaviour I'd like to take advantage of. However, if I'm reallocating memory because I want to (for example) insert a char at the start of an existing string, I don't want realloc() to copy the memory. I'll end up copying the entire string with realloc(), then copying it again manually to free up the first array element.
Is it possible to determine what realloc() will do? If so, is it possible to achieve in a cross-platform way?
realloc()'s behavior is likely dependent on its specific implementation. And basing your code on that would be a terrible hack which, to say the least, violates encapsulation.
A better solution for your specific example is:
Find the size of the current buffer
Allocate a new buffer (with malloc()), greater than the previous one
Copy the prefix you want to the new buffer
Copy the string in the previous buffer to the new buffer, starting after the prefix
Release the previous buffer
As noted in the comments, case 3 in the question (no memory) is wrong; realloc() will return NULL if there is no memory available [question now fixed].
Steve McConnell in 'Code Complete' points out that if you save the return value from realloc() in the only copy of the original pointer when realloc() fails, you've just leaked memory. That is:
void *ptr = malloc(1024);
...
if ((ptr = realloc(ptr, 2048)) == 0)
{
/* Oops - cannot free original memory allocation any more! */
}
Different implementations of realloc() will behave differently. The only safe thing to assume is that the data will always be moved - that you will always get a new address when you realloc() memory.
As someone else pointed out, if you are concerned about this, maybe it is time to look at your algorithms.
Would storing your string backwards help?
Otherwise...
just malloc() more space than you need, and when you run out of room, copy to a new buffer. A simple technique is to double the space each time; this works pretty well because the larger the string (i.e. the more time copying to a new buffer will takes) the less often it needs to occur.
Using this method you can also right-justify your string in the buffer, so it's easy to add characters to the start.
If obstacks are a good match for your memory allocation needs, you can use their fast growing functionality. Obstacks are a feature of glibc, but they are also available in the libiberty library, which is fairly portable.
No - and if you think about it, it can't work. Between you checking what it's going to do and actually doing it, another process could allocate memory.
In a multi-threaded application this can't work. Between you checking what it's going to do and actually doing it, another thread could allocate memory.
If you're worried about this sort of thing, it might be time to look at the data structures you're using to see if you can fix the problem there. Depending on how these strings are constructed, you can do so quite efficiently with a well designed buffer.
Why not keep some empty buffer space in the left of the string, like so:
char* buf = malloc(1024);
char* start = buf + 1024 - 3;
start[0]='t';
start[1]='o';
start[2]='\0';
To add "on" to the beginning of your string to make it "onto\0":
start-=2;
if(start < buf)
DO_MEMORY_STUFF(start, buf);//time to reallocate!
start[0]='o';
start[1]='n';
This way, you won't have to keep copying your buffer every single time you want to do an insertion at the beginning.
If you have to do insertions at both the beginning and end, just have some space allocated at both ends; insertions in the middle will still need you to shuffle elements around, obviously.
A better approach is to use a linked list. Have each of your data objects allocated on a page, and allocate another page and have a link to it, either from the previous page or from an index page. This way you know when the next alloc fails, and you never need to copy memory.
I don't think it's possible in cross platform way.
Here is the code for ulibc implementation that might give you a clue how to do itin platform dependent way, actually it's better to find glibc source but this one was on top of google search :)

Resources