Can I assume that calling realloc with a smaller size will free the remainder?

北战南征 提交于 2019-11-28 20:19:57

Yes, guaranteed by the C Standard if the new object can be allocated.

(C99, 7.20.3.4p2) "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."

Yes—if it succeeds.

Your code snippet shows a well-known, nefarious bug:

char* b = (char*) realloc(a, 5);

If this succeeds, the memory that was previously allocated to a will be freed, and b will point to 5 bytes of memory that may or may not overlap the original block.

However, if the call fails, b will benull, but a will still point to its original memory, which will still be valid. In that case, you need to free(a) in order to release the memory.

It's even worse if you use the common (dangerous) idiom:

a = realloc(a, NEW_SIZE);     // Don't do this!

If the call to realloc fails, a will be null and its original memory will be orphaned, making it irretrievably lost until your program exits.

This depends on your libc implementation. All of the following is conformant behaviour:

  • doing nothing, ie letting the data remain where it is and returning the old block, possibly re-using the now unused bytes for further allocations (afaik such re-use is not common)
  • copying the data to a new block and releasing the old one back to the OS
  • copying the data to a new block and retaining the old one for further allocations

It's also possible to

  • return a null pointer if a new block can't be allocated

In this case, the old data will also remain where it is, which can lead to memory leaks, eg if the return value of realloc() overwrites the only copy of the pointer to that block.

A sensible libc implementation will use some heuristic to determine which solution is most efficient.

Also keep in mind that this description is at implementation level: Semantically, realloc() always frees the object as long as allocation doesn't fail.

The realloc function has the following contract:

void* result = realloc(ptr, new_size)

  • If result is NULL, then ptr is still valid and unchanged.
  • If result is non-NULL, then ptr is now invalid (as if it had been freed) and must not ever be used again. result is now a pointer to exactly new_size bytes of data.

The precise details of what goes on under the hood are implementation-specific - for example result may be equal to ptr (but additional space beyond new_size must not be touched anymore) and realloc may call free, or may do its own internal free representation. The key thing is that as a developer you no longer have responsibility for ptr if realloc returns non-null, and you do still have responsibility for it if realloc returns NULL.

It seems unlikely that 19995 bytes were freed. What's more likely is that realloc replaced the 20000-byte block by another 5-byte block, that is, the 20000-byte block was freed and a new 5-byte block was allocated.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!