Donald Smith
Donald Smith

Reputation: 31

How do new/malloc seem to remember amount of data allocated?

Why does this not cause a memory leak? I allocate space for a long long on the heap, and then change the pointer I get back to a char*. Afterwards, I call delete (or free, in the second example) on this pointer. Both of these examples do not seem to cause a memory leak.

#include <stdlib.h>

struct leaky {
   long long* testptr;
   leaky() {testptr = new long long; }
   ~leaky() { void* newptr = (void*) testptr;
              char* newptr2 = (char*) newptr;
              delete newptr2; }
};

struct leaky2 {
   long long* testptr;
   leaky2() { testptr = (long long*) malloc(sizeof(long long)); }
   ~leaky2() { void* newptr = (void*) testptr;
               char* newptr2 = (char*) newptr;
               free (newptr2); }
};

int main() {
   while (true) {
      {
         leaky leak = leaky();
      }
   }
}

I tested this on: gcc version 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC) on a Unix system.

Upvotes: 3

Views: 645

Answers (4)

Lloyd Crawley
Lloyd Crawley

Reputation: 616

When using malloc or new the space used consists of both "overhead" (info relating to the size of used and free blocks of memory, the actual pointer to the space you need) and "payload" (the memory being used).

One form of jargon used for this book keeping info is an "initialisation record" that may resemble the following struct

struct InitRecord
{
  int memBlockSize;
  void* mem;
};

This is how malloc remembers how much mem you used. A good way to understand further (and a fun exercise!) is to create your own heap allocator.

Good reference material here http://www.cs.ucsb.edu/~rich/class/cs170/labs/lab1.malloc/index.html

and here

http://systematicgaming.wordpress.com/2008/08/05/memory-management-introduction/

Upvotes: 0

cHao
cHao

Reputation: 86525

  1. Any pointer to memory can be converted to a char* and back and have the same value. So casting to char* just changes how the compiler interprets the value (what sizeof(*ptr) returns, etc). It doesn't change the value of the pointer.

  2. operator delete and free() accept a void*. So by the time either is asked to free the memory, any notion of "type" is gone from it anyway. They have to be able to account for that and work with the memory without knowing anything about what those bytes used to be.

    For reference, they often do so by allocating a little extra memory and recording the size of that memory in some bytes right before the address returned to you. But that's an implementation detail; don't rely on it.

Upvotes: 0

The first piece of code is undefined behavior, as you cannot delete from a type that is unrelated to what you new-ed. The second case is correct, so we can discuss that one.

The interface to malloc and free is based on void*, so the type does not quite matter here, but the question remains: how does free know how much was allocated with malloc? and the answer is that it is implementation defined. It can be done in different ways. The allocator can acquire a larger block of memory and store the information in that extra space. In some cases malloc allocates from different pools for different fixed sizes (specially for small objects), so the information need not be tracked with a possibly small object. In those cases the implementation of free only needs to figure out what pool the memory came from and return the block to the pool.

Upvotes: 6

Ben
Ben

Reputation: 693

malloc associates some bookkeeping information with the value of the address it returns to you (sometimes in the memory region just before the address). This bookkeeping information contains the size of the allocation. Casting addresses around doesn't change the value of this address, only the interpretation of it by your code.

Upvotes: 4

Related Questions