First question:
realloc(array, 0)
is not equivalent to free(array)
.
The standard (C99, §7.20.3.4 ¶1) says:
The realloc
function deallocates the old object pointed to by ptr
and returns a pointer to a new object that has the size specified by size
.
and gives no "special case" for a size==0
; so, you are getting a pointer to an object of size zero - but which potentially is still an object, and still has to be freed.
Interestingly, I think the realloc
may simply fail in such a circumstance, returning NULL
; in this case, in your code the memory is leaked, since, when realloc
fails, it does not free the original memory block you passed to it (which is the reason why you never do array = realloc(array, size)
but you always use an intermediate variable to check for NULL
in order to avoid memory leaks).
Actually, the standard does specify the size==0
implementation-defined behavior for all the memory allocation functions, not just for malloc
as I remembered; so, the behavior is implementation defined, as desribed below:
More intuitively, realloc
is "conceptually equivalent" to to malloc
+memcpy
+free
on the other pointer, and malloc
-ing a 0-byte chunk of memory returns either NULL
either a unique pointer, not to be used for storing anything (you asked for 0 bytes), but still to be free
ed. So, no, don't use realloc
like that, it may work on some implementations (namely, Linux) but it's certainly not guaranteed.
Also, it's not clear how you deduced that free
doesn't work. I can think of two ways you may have been convinced of this:
- the value of
array
and of the data it points to is unchanged;
- the allocated memory in the task manager/
top
/whatever doesn't decrease.
For the first case, that's normal; when you free a pointer, it doesn't magically get wiped - your pointer still points to where it pointed, but that memory is no longer yours - it's now back to the C runtime, which will probably re-give it away in a future malloc
. That's why that thing is called a "dangling pointer", and many people after a free
set it to NULL
to avoid writing again in a space of memory that has already been released.
As for the second, it's common policy for allocators not to give back memory to the operating system immediately (unless we are talking about really big chunks); the idea is that probably the application will need such memory again soon, and keeping that memory for the current process can avoid continuous system calls to take/give memory from the OS. Since system utilities for monitoring the memory used normally can only see what the OS has given to the process, it's normal that they don't show any memory usage decrease.
By the way, remember that, if you char ** array
contains pointers to stuff allocated with malloc
, you have to free
them first, otherwise you're leaking memory.
Second question:
C strings are null-terminated, i.e. the last character of the string is always a \0
to mark the string ends, while strlen
gives you the length of the string excluding the null terminator. So, if you don't add that +1
you are allocating one char
less than the memory needed to actually store your string.
Addendum
By doesn't work I mean that it did crash (the problem might have been somewhere else ofc) but when I changed it to realloc(X, 0) it did work, in the sense of deleting used dynamic used memory
As the manpage says,
Crashes in malloc(), calloc(), realloc(), or free() are almost always related to heap corruption, such as overflowing an allocated chunk or freeing the same pointer twice.
You probably have some other bug in your code, but without seeing it it's impossible to tell what/where it goes wrong.
realloc(array, 0)
is not equivalent tofree(array)
. This idiom is just wrong. I don't have time to write an answer at the moment but hopefully someone can explain it well. – Stodderfree
doesn't work? – Witwatersrandfree
is make memory available for subsequent allocations and not decrement some free space counter reported byps
,memfree
or similar system utility. – Typecastfree
, there is a bug in your code.realloc(X, 0)
may or may not be equivalent tofree(X)
. It is implementation-dependent. On your system they are obviously not equivalent becausefree
crashes andrealloc
does not. By disabling the crash you simply pretend the bug does not exist. It is however still there. I would recommend trying to find it. – Choroidarray = realloc(array, newSize);
is bad. If therealloc
fails, the old memory won't befree
d butNULL
will be returned and clobber the old pointer, leaving you with a memory leak. Correct istmp = realloc(array, newSize); if (tmp == NULL) {Do something appropriate here, keeping in mind that array still points to the original block and is still valid.} else {array = tmp;}
. – Bronchiectasis