Imagist
Imagist

Reputation: 18534

C and C++: Freeing PART of an allocated pointer

Let's say I have a pointer allocated to hold 4096 bytes. How would one deallocate the last 1024 bytes in C? What about in C++? What if, instead, I wanted to deallocate the first 1024 bytes, and keep the rest (in both languages)? What about deallocating from the middle (it seems to me that this would require splitting it into two pointers, before and after the deallocated region).

Upvotes: 10

Views: 2993

Answers (7)

evoskuil
evoskuil

Reputation: 1039

When not bound to a file mmap (with MAP_ANONYMOUS) creates a memory allocation that allows control over truncation and expansion using mremap (with/without MREMAP_MAYMOVE).

MAP_ANONYMOUS mmap implementations may internally just forward to malloc/free, but realloc() does not guarantee that a truncation will not be moved. As mremap will not move unless MREMAP_MAYMOVE is provided, it can be used for unmovable truncation.

MREMAP_MAYMOVE: If this flag is specified, then the kernel is permitted to relocate the mapping to a new virtual address, if necessary.

While msvc doesn't provide mmap, the same can be achieved with Win32 APIs.

Upvotes: 0

Roddy
Roddy

Reputation: 68104

Don't try and second-guess memory management. It's usually cleverer than you ;-)

The only thing you can achieve is the first scenario to 'deallocate' the last 1K

char * foo = malloc(4096);

foo = realloc(foo, 4096-1024);

However, even in this case, there is NO GUARANTEE that "foo" will be unchanged. Your entire 4K may be freed, and realloc() may move your memory elsewhere, thus invalidating any pointers to it that you may hold.

This is valid for both C and C++ - however, use of malloc() in C++ is a bad code smell, and most folk would expect you to use new() to allocate storage. And memory allocated with new() cannot be realloc()ed - or at least, not in any kind of portable way. STL vectors would be a much better approach in C++

Upvotes: 12

Stephen Veiss
Stephen Veiss

Reputation: 1384

You don't have "a pointer allocated to hold 4096 bytes", you have a pointer to an allocated block of 4096 bytes.

If your block was allocated with malloc(), realloc() will allow you to reduce or increase the size of the block. The start address of the block won't necessarily stay the same, though.

You can't change the start address of a malloc'd memory block, which is really what your second scenario is asking. There's also no way to split a malloc'd block.

This is a limitation of the malloc/calloc/realloc/free API -- and implementations may rely on these limitations (for example, keeping bookkeeping information about the allocation immediately before the start address, which would make moving the start address difficult.)

Now, malloc isn't the only allocator out there -- your platform or libraries might provide other ones, or you could write your own (which gets memory from the system via malloc, mmap, VirtualAlloc or some other mechanism) and then hands it out to your program in whatever fashion you desire.

For C++, if you allocate memory with std::malloc, the information above applies. If you're using new and delete, you're allocating storage for and constructing objects, and so changing the size of an allocated block doesn't make sense -- objects in C++ are a fixed size.

Upvotes: 5

KV Prajapati
KV Prajapati

Reputation: 94653

http://en.wikipedia.org/wiki/New_(C%2B%2B)

SUMMARY:In contrast to C's realloc, it is not possible to directly reallocate memory allocated with new[]. To extend or reduce the size of a block, one must allocate a new block of adequate size, copy over the old memory, and delete the old block. The C++ standard library provides a dynamic array that can be extended or reduced in its std::vector template.

Upvotes: 1

anon
anon

Reputation:

You can use realloc() to apparently make the memory shorter. Note that for some implementations such a call will actually do nothing. You can't free the first bit of the block and retain the last bit.

If you find yourself needing this kind of functionality, you should consider using a more complex data structure. An array is not the correct answer to every programming problem.

Upvotes: 1

laalto
laalto

Reputation: 152927

If you have n bytes of mallocated memory, you can realloc m bytes (where m < n) and thus throw away the last n-m bytes.

To throw away from the beginning, you can malloc a new, smaller buffer and memcpy the bytes you want and then free the original.

The latter option is also available using C++ new and delete. It can also emulate the first realloc case.

Upvotes: 5

Zed
Zed

Reputation: 57678

You can make it shorter with realloc(). I don't think the rest is possible.

Upvotes: 1

Related Questions