3

Is there a way to get the size of previously allocated memory on a heap?
For example:

//pseudo-code

void* p = operator new (sizeof(int) * 3);
unsigned size = getSomeHow(p);  
Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
There is nothing we can do
  • 23,727
  • 30
  • 106
  • 194
  • Do you mean, previously allocated in your function's code, your thread's control flow or by your process, on the heap, overall? – einpoklum Aug 06 '13 at 11:58

3 Answers3

8

You can't do it at all times, since operator new() can be overloaded in any reasonable way and maybe even without using the runtime heap.

In case operator new() is implemented with malloc() in Visual C++ you can use _msize().

sharptooth
  • 167,383
  • 100
  • 513
  • 979
5

Although Sharptooth is right in his answer (new can be overloaded), the solution might be just in this fact. By overloading new, you can easily add your own implementation of new and delete. In your implementation of new you should:

  • EDIT: round the size to the next multiple of 8 bytes
  • add 8 bytes to the size requested by the application
  • call the systems memory allocate routine (e.g. HeapAlloc in Windows)
  • fill in the originally requested size in the first 8 bytes
  • add 8 to the returned pointer and return this back to the application

The delete operator should do the opposite:

  • subtract 8 bytes from the pointer given by the application
  • call the systems memory deallocate routine

If you do it this way, make sure to implement all flavours of new and delete (throwing and non-throwing, new and new[], delete and delete[], ...).

Also be careful with 3rd party libraries. They sometimes put the call to new in their compiled code in their DLL, but but the call to delete in the header. This means that new and delete will use different implementations and your application will crash.

EDIT:

The rounding to the multiple of 8 bytes and the addition of 8 bytes is needed because data should be stored at an addres that is a multiple of its size:

  • chars can be stored anymore
  • shorts must be stored on an even address
  • longs must be stored on an address that's a multiple of 4
  • doubles must be stored on an address that's a multiple of 8

Since doubles are the largest native data type that I'm aware of, we round to a multiple of 8 bytes and we add 8 bytes to make sure that keep these requirements.

Patrick
  • 23,217
  • 12
  • 67
  • 130
  • 1
    Why exactly 8 bytes and not "enough bytes to store a `size_t` variable"? – sharptooth Nov 01 '10 at 10:32
  • Because the native data types need to be stored on an address that is a multiple of its size. Normally, the biggest data type is double, which is 8 bytes. Therefore, we need to add 8 bytes to the size and to the pointer to keep it a multiple of 8 bytes. (add a slight correction to my post to make sure we keep these multiple of 8 bytes). – Patrick Nov 01 '10 at 11:18
  • Okay, I see. Then shoudn't it be `max( sizeof( double ), sizeof( void* ) )` or something like that so that code is portable to 1024 (or whatever) bit computers? – sharptooth Nov 01 '10 at 11:52
1
  • You can rewrite the new operator to call malloc() and store the size in a global std::map<void*, size> alloc.

Then this getSomeHow() function will behave like you want:

getSomeHow(void *p){
  return alloc[p]; 
}
  • You can also write your own malloc() and set the loader to use your malloc instead of the standard one. I have done this for tracing purpose, it works fine.
Ben
  • 7,372
  • 8
  • 38
  • 46
  • That's great, but why not just allocate a slightly bigger block, write the allocated size at its start and return an offset pointer? – sharptooth Nov 01 '10 at 10:31
  • Hum yes, it's much better actually ! – Ben Nov 01 '10 at 10:39
  • @Ben would you please provide some hint how to write my own malloc? It interests me very much. Thanks in advance – There is nothing we can do Nov 01 '10 at 10:53
  • @There is nothing we can do : which os are you running ? – Ben Nov 01 '10 at 11:10
  • You have to write a C file with your own malloc() realloc() and free(), (function declarations must be the same as in `stdlib.h`). Then compile it as a dynamic library (dll), and tell the system to load *your* malloc library. Unfortunately I have *no* idea how to do this last thing in windows 7. Maybe someone here can help. – Ben Nov 01 '10 at 15:07