using realloc in c - c++

i am using void *realloc(void *pointer, size_t size); to increase the size of my pointer. how does realloc work?
does it create a nre address space, and copy the old value to the new address space and returns a pointer this address? or it just allocates more memory and binds it to the old one?

#Iraklis has the right answer: it does the second (if it can get away with it) or the first (but only if it has to).
However, sometimes it can do neither, and will fail. Be careful: If it can't resize your data, it will return NULL, but the memory will NOT be freed. Code like this is wrong:
ptr = realloc(ptr, size);
If realloc returns NULL, the old ptr will never get freed because you've overwritten it with NULL. To do this properly you must do:
void *tmp = realloc(ptr, size);
if(tmp) ptr = tmp;
else /* handle error, often with: */ free(ptr);
On BSD systems, the above is turned into a library function called reallocf, which can be implemented as follows:
void *reallocf(void *p, size_t s)
{
void *tmp = realloc(p, s);
if(tmp) return tmp;
free(p);
return NULL;
}
Allowing you to safely use:
ptr = reallocf(ptr, size);
Note that if realloc has to allocate new space and copy the old data, it will free the old data. Only if it can't resize does it leave your data intact, in the event that a resize failure is a recoverable error.

It depends! If its unable to resize the memory region in place then it allocates a new memeory region, copy the old data and free the old memory.

You're misusing the term "address space". All of the memory of your process exists within a single address space. The memory not used by your program, its global variables, and its stack are known as the "heap". malloc and realloc (and calloc, which is just malloc and clear) allocate memory from the heap. Most implementations of realloc will check if there is enough (size bytes) free space starting at pointer (which must point to a block previously allocated by malloc or realloc -- realloc knows how large that block is) and, if so, just increase the size of the block allocated at the location given by pointer and return, with no copying. If there isn't enough space, it will do the equivalent of newptr = malloc(size); memcpy(newptr, pointer, size_of_old_block); free(pointer); return newptr; ... that is, it will allocate a block big enough to hold size bytes, copy the data at pointer to that block, free the old block, and return the address of the new block.

I think the answer is function is dependent on the requested size and available heap.
From the programmers perspective, I think all we get guaranteed is that pointer is non-null if the new allocation is successful. The pointer may, therefore, remain unchanged even though it now points to a larger block of memory represented by size_t.

Realloc does not change the size of your pointer, the size of pointers is always the same on the same architecture. It changes the size of the allocated memory to which your pointer points. The way it works is described here: http://msdn.microsoft.com/en-us/library/xbebcx7d.aspx. In short, yes, it allocates more memory leaving your content unchanged; if the memory must be moved, it copies the content. OF course, you can specify a shorter size, in which case it trims the allocated memory, again leaving the content untouched.

Related

How to pass exact memory size to free() if void* allocation size is known

As far as I know ; In c++ and c delete operator or free() function can know the size of allocated memory from pionter data type and delete can call the destructor automatically.
If the allocated pointer is registered using a kind of singleton static dynamic array which don't use new operator in its mechanism (ie. malloc only)
in oveloaded new pointer. this array register void* pointers and take the size of that pointer from overloaded new operator
Ex.
void * operator new (size_t sz) {
void * m = malloc (sz);
Dynamic_Array::get_instance()->add(m,sz) ; //registering pointer
return m ;
}
so My question is how to use the information about size to release the exact allocated memory that I forget to delete using the destructor of this array.
Ex.
Dynamic_Array::~Dynamic_Array() {
int index = 0;
while(index < storage_size) //storage_size: total number of pointers in array
/* storage is void** array which register
allocated pointers as void* and use classic memset and memcpy to enlarge*/
{
if (storage[index] != NULL) printf("Pointer : %d was not deleted\n", storage[index]);
//how to use delete or free here to delete void* pointer but with known size of memory
index ++;
}
}
Thank you.
As far as I know ; In c++ and c delete operator or free() function can know the size of allocated memory from pionter data type
No. The delete operator calls the free() function; the free() function knows the size from metadata associated with the pointer somehow, for example a length word in the preceding word of memory.
and delete can call the destructor automatically.
Yes.
My question is how to use the information about size to release the exact allocated memory that I forget to delete using the destructor of this array.
You don't need to know. See above.
in C,
The free() function uses the data structure in the heap that surrounds the allocated memory.
That data structure includes the real start address of the allocated memory, the address of the prior memory block in the heap, and the address of the next memory block in the heap.
In general, the heap is actually two linked lists.
One is allocated memory and one is free memory.
a malloc operation takes an appropriately sized block from the free linked list and puts it into the allocated memory linked list.
This may involve breaking a larger free memory block into two smaller memory blocks, where one is moved to the allocated memory linked list and pointer are adjusted in the free memory list for the new block
A free removes the entry from the allocated memory linked list and puts it into the free linked list.
then if the free linked list contains two adjacent memory blocks, then those two memory blocks are combined into a single/larger memory block.
There are several algorithms that may be used to determine exactly which free area is broken up/moved to the allocated memory list.

c++ realloc same pointer warranty

Using the std::realloc function:
If the new size is smaller, does it always have warranty to keep the memory block on the same position and only make it smaller, or it can move sometimes the whole block?
The reason to ask this, is that we'are writing a large and very hard code, and it is useful to make read only all the variables we need to leave unchanged, to obtain compiler's errors, when we try to change the wrong variable.
#include<cstdlib>
#include<iostream>
using namespace std;
int main(){
//From 10,000,000 unsigned ints to 10 unsigned ints
unsigned int * const array=new unsigned int[10000000];
cout<<array<<endl;
realloc(array,10*sizeof(unsigned int));
cout<<array<<endl;
delete array;
return 0;
}
Although I agree with the other answers in that you should not depend on it, there is an answer to be found in the glibc source. (I am assuming that you are using glibc, as you have not (yet) answered my comment asking which C library you are using)
EDIT: Using realloc on memory allocated by new is indeed disallowed, as other answers have mentioned.
Memory allocated without internally using mmap
If a block of memory is not allocated with mmap, __libc_realloc calls the _int_realloc function, which contains the following snippet of code:
if ((unsigned long) (oldsize) >= (unsigned long) (nb))
{
/* already big enough; split below */
newp = oldp;
newsize = oldsize;
}
This makes the pointer to the new memory equal the pointer to the old memory and sets the size accordingly. Note the split below comment; the old memory block may be resized to the requested size, but is not moved.
Memory allocated internally using mmap
If the memory was internally allocated using mmap, there are two ways of resizing the memory area; mremap_chunk or a series of calls to malloc, memcpy and free. If the mremap_chunk function is available, it is used instead of the latter option.
Memory reallocated using mremap_chunk
The function mremap_chunk contains this snippet of code
/* No need to remap if the number of pages does not change. */
if (size + offset == new_size)
return p;
If the number of pages does not change from the old size to the new size, there is no need to remap and the old pointer is returned.
Memory reallocated using malloc, memcpy and free
If mremap_chunk is not available, the __libc_realloc source continues with the following:
/* Note the extra SIZE_SZ overhead. */
if (oldsize - SIZE_SZ >= nb)
return oldmem; /* do nothing */
If the oldsize variable minus the chunk size is more than or equal to the new size, just return the old memory.
Well then, here we are. In all cases, glibc returns a pointer to the old memory, not moving it (but possibly resizing it). If you are using glibc (and can somehow guarantee that the only C library you are using it with is glibc, and can guarantee that it won't change at some point in the future), you are able to rely on the behavior that realloc does not move a block of memory if the requested size is equal to or less than the old size.
No!! If realloc succeeds, the old pointer (unless it was a nullpointer) is indeterminate.
Also, do not mix incompatible memory-management-functions (assume incompatibility unless guaranteed otherwise).
realloc only has the guarantees explicitly given in the standard:
If return-value is non-0: New pointer points to of at least size byte, the first min(oldsize, newsize) being equal to the passed block.
Else if size is non-0, nothing happened to the passed block.
Else the old block may have been deallocated, or not.
Moral: Never pass a 0 size to realloc, and only use the old pointer for anything (including comparison to the new pointer), if realloc failed (or you passed a nullpointer).
7.22.3.5 The realloc function
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
2 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.
3 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
4 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.
C99 draft 7.20.3.4 says:
[#4] 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.
You should not assume it.
And also: don't mix new and realloc as πάντα already wrote in the comments.
Nothing's guaranteed about realloc. It might shrink the block in place, or it might allocate a new one and copy the data. It might also fail.
An important point: realloc is only for reallocating memory that was previously allocated by malloc. In your code above, you are using new which has no equivalent for reallocation.
Also realloc actually returns the address of the new memory block, so in your code above you will be a) leaking this and b) referencing/freeing potentially already de-allocated memory.

"Delete" not de-allocating dynamic memory [duplicate]

This question already has answers here:
C++ delete - It deletes my objects but I can still access the data?
(13 answers)
Closed 9 years ago.
I'm facing an issue. I wrote the following programme:
void main()
{
int *ptr;
ptr=new int;
cout<<ptr<<endl;
cout<<&ptr<<endl;
delete ptr;
// ptr= NULL;
cout<<ptr<<endl;
cout<<&ptr<<endl;
}
The output of the programme is:
0x00431810
0x0018FF44
0x00431810
0x0018FF44
"&ptr" would definitely be the same because it is ptr's own address. But 1st and third line of output clearly shows that "ptr" is pointing to the same memory location even after the "delete" is called. Why? If this is the case why do we have "delete" and not just rely on NULLING the pointer. I know that more than one pointers can point to a memory location but yeah "delete" is useless. No ? That's so confusing. please help. I've an exam tomorrow.
delete ptr does not change the value of the pointer, but it does free the memory.
Note that dereferencing ptr after freeing the memory would trigger undefined behaviour.
When you call new, you are asking the computer to allocate some memory on the heap and returns a pointer to where that is on the heap.
Calling delete does the opposite in that it tells the computer to free the memory the pointer is pointing to from the heap. This means that it can be reused by your program at a later stage.
However, it does not change the value of the pointer. It is good practise to set the pointers value to NULL. This is because, where the pointer is now pointing to could contain anything (the computer is free to reuse this memory for something else). Were you to use this pointer, it is undefined what will happen.
If you just change the pointer to NULL, then all that does it forget where you allocated the memory. Because C++ is not a managed language, it won't detect you don't have any pointer to that memory, so the memory will become lost as you can't access it (you don't know where it is) but the computer can't reuse it (it doesn't know you are done with it).
If you use a managed language like C# or Java, when there are no pointers to something on the heap, the computer frees it (known as Garbage Collection) but this comes with performance overheads so C++ leaves it up to the programmer.
pointer doesn't know if the memory is valid or corrupted. You can make pointer to point at any address that you can address (that will fit into pointer). For example on my machine pointer has 8 bytes size so I can do
int main(int argc, char** argv) {
int *ptr;
ptr=new int;
cout<<ptr<<endl;
cout<<&ptr<<endl;
delete ptr;
//ptr= NULL;
cout<<ptr<<endl;
cout<<&ptr<<endl;
ptr = (int*) 0xffffffff;
cout<<ptr<<endl; //prints 0xffffffff
ptr = (int*) 0xffffffffffffffff;
cout<<ptr<<endl; //prints 0xffffffffffffffff
ptr = (int*) 0xffffffffffffffff1;
cout<<ptr<<endl; //prints 0xfffffffffffffff1 truncated
ptr = (int*) 0xffffffffffffffff321;
cout<<ptr<<endl; //prints 0xfffffffffffff321 truncated
return 0;
}
When you are using new it will allocate memory at some address on the heap and return you a pointer to this address.
void* operator new (std::size_t size) throw (std::bad_alloc);
Pointer and memory are two distinguished things. In particular you can even specify an address which you want to use for allocation by hand(using placement new syntax):
int* ptr = new (0xff1256) int;
//correct if the memory at 0xff1256 is preallocated
//because placement new only creates object at address
//doesn't allocate memory
"ptr" is pointing to the same memory location even after the "delete"
is called. Why?
In the same way delete ptr only deallocates memory, leaving the pointer intact (this is a good practice though to assign NULL to a pointer immediately after call to delete). It only deallocate the memory, it is not interested in your pointer but in the address where to free memory. Allocating memory or deallocating it is done by operating system (i.e.the memory is being marked as allocated).
From the documentation,
Deallocates the memory block pointed by ptr (if not null), releasing
the storage space previously allocated to it by a call to operator new
and rendering that pointer location invalid.
That means, delete marks the location to be reused by any other process for any other purpose. It never says that, it will initialize the memory block to any random value, so that the earlier stored data can never be accessed again. So, there is always the possibility of having your data even after the call to delete. But, again, it is just one of the possibility of Undefined Behavior. Thats' why coders, make the pointer NULL after deallocating it.

Does c++ realloc function applies delete operation for old data block if moving data to different block?

The function may move the memory block to a new location, in which case the new location is returned.
For example I have a pointer to an array:
int *arr; // somewhere next it initialized, filled with elements and etc
Somewhere I need to:
void* location = realloc(arr, NEW_SIZE);
What will happen with old memory block place?
If realloc return pointer that not math to arr, should i use next code?:
delete arr;
arr = (int*)location;
The function realloc is inherited from good old C. It does not run destructors or do any other C++ magic. It can also only be applied to blocks allocated using malloc (and friends) -- it can not be used for blocks allocated using 'new'.
Rule #1: dont mix new/delete with malloc/free.
If you're allocating with malloc() in the first place and you need a bigger heap space then you need to call realloc() which will return you a new pointer which may not map to the same memory areas as arr therefore you should not use it.
Free malloc'ed/realloc'ed space with free
realloc(void *ptr, size_t new_size) requires the given area of memory that ptr points to to be previously allocated by malloc(), calloc() or realloc() and not yet freed with free(), otherwise, the results are undefined.
Use realloc only with malloc, calloc or another realloc and clean it up with free.
In C++ use always new with delete and new[] with delete[].

Where my memory is alloced, Stack or Heap, Can I find it at Run-time?

I know that memory alloced using new, gets its space in heap, and so we need to delete it before program ends, to avoid memory leak.
Let's look at this program...
Case 1:
char *MyData = new char[20];
_tcscpy(MyData,"Value");
.
.
.
delete[] MyData; MyData = NULL;
Case 2:
char *MyData = new char[20];
MyData = "Value";
.
.
.
delete[] MyData; MyData = NULL;
In case 2, instead of allocating value to the heap memory, it is pointing to a string literal.
Now when we do a delete it would crash, AS EXPECTED, since it is not trying to delete a heap memory.
Is there a way to know where the pointer is pointing to heap or stack?
By this the programmer
Will not try to delete any stack memory
He can investigate why does this ponter, that was pointing to a heap memory initially, is made to refer local literals? What happened to the heap memory in the middle? Is it being made to point by another pointer and delete elsewhere and all that?
Is there a way to know where the pointer is pointing to heap or stack?
You can know this only if you remember it at the point of allocation. What you do in this case is to store your pointers in smart pointer classes and store this in the class code.
If you use boost::shared_ptr as an example you can do this:
template<typename T> void no_delete(T* ptr) { /* do nothing here */ }
class YourDataType; // defined elsewhere
boost::shared_ptr<YourDataType> heap_ptr(new YourDataType()); // delete at scope end
YourDataType stackData;
boost::shared_ptr<YourDataType> stack_ptr(&stackData, &no_delete); // never deleted
As soon as you need that knowledge you have already lost. Why? Because then even if you omit the wrong delete[], you still have a memory leak.
The one who creates the memory should always be the one who deletes it. If at some occasion a pointer might get lost (or overwritten) then you have to keep a copy of it for the proper delete.
There is no way in Standard C++ of determining whether a pointer points to dynamically allocated memory or not. And note that string literals are not allocated on the stack.
As most of the users said here there's no standard way to discover which memory you're dealing with.
Also, as many users pointed out, it;s a kinda perverted situation where you pass a pointer to a function which should delete it automatically if it's allocated on heap.
But if you insist, nevertheless there are some ways to discover which memory belongs to which type.
You actually deal with 3 types of memory
Stack
Heap
Global
For instance:
char* p = new char[10]; // p is a pointer, points to heap-allocated memory
char* p = "Hello, world!"; // p is a pointer, points to the global memory
char p[] = "Hello, world!"; // p is a buffer allocated on the stack and initialized with the string
Now let's distinguish them. I'll describe this in terms of Windows API and x86 assembler (since this is what I know :))
Let's start from stack memory.
bool IsStackPtr(PVOID pPtr)
{
// Get the stack pointer
PBYTE pEsp;
_asm {
mov pEsp, esp
};
// Query the accessible stack region
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pEsp, &mbi, sizeof(mbi)));
// the accessible stack memory starts at mbi.BaseAddress and lasts for mbi.RegionSize
return (pPtr >= mbi.BaseAddress) && (pPtr < PBYTE(mbi.BaseAddress) + mbi.RegionSize);
}
If the pointer is allocated on the stack of another thread you should get its stack pointer by GetThreadContext instead of just taking the EIP register value.
Global memory
bool IsGlobalPtr(PVOID pPtr)
{
MEMORY_BASIC_INFORMATION mbi;
VERIFY(VirtualQuery(pPtr, &mbi, sizeof(mbi)));
// Global memory allocated (mapped) at once for the whole executable
return mbi.AllocationBase == GetModuleHandle(NULL);
}
If you're writing a DLL you should put its module handle (which is actually its base mapping pointer) instead of GetModuleHandle(NULL).
Heap
Theoretically you may assume that if the memory is neither global nor stack - it's allocated on heap.
But there's is actually a big ambiguity here.
You should know that there're different implementations of the heap (such as raw Windows heap accessed by HeapAlloc/HeapFree, or CRT-wrapped malloc/free or new/delete).
You may delete such a block via delete operator only if you know for sure it was either stack/global pointer or it was allocated via new.
In conclusion:
It's a kinda pervert trick. Should not be used generally. Better to provide some extra information with the pointer which tells how to release it.
You can only use it if you know for sure on which heap the memory was allocated (in case it's a heap memory).
I think there is no (easy) way how to tell where the memory is allocated (you might be able to determine it using a debugger, perhaps, but that is obviously not what you want). The bottom line is: never do the thing you did in case 2.
In case 2, MyData = "Value" causes a memory leak since there is no longer a reference to the memory returned from new.
There is no easy way or standard way for doing this. You can intercept the heap allocation function(s) and put each memory allocated zone in a list. Your "IsHeap" function should check if the zone passed to the function is the one from the list. This is just a hint - it is almost impossible to do this in a cross-platform manner.
But then again - why would you need that?