8

I'm working on a C++ library, one of whose functions returns a (freshly allocated) pointer to an array of doubles. The API states that it is the responsibility of the caller to deallocate the memory.

However, that C++ library used to be implemented in C and the function in question allocates the memory with malloc(). It also assumes that the caller will deallocate that memory with free().

Can I safely replace the call to malloc() with a call to new? Will the existing client code (that uses free() break if I do so? All I could find so far was the official documentation of free(), which states that

If ptr does not point to a block of memory allocated with [malloc, calloc or realloc], it causes undefined behavior.

But I believe this was written before C++ came along with its own allocation operators.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
lindelof
  • 34,556
  • 31
  • 99
  • 140
  • 7
    no. it really depends on the library, but generally, no. – thang Mar 14 '14 at 13:25
  • 4
    The documentation is accurate. It is undefined behavior. – Benjamin Lindley Mar 14 '14 at 13:27
  • 2
    See this: [Can I free() pointers allocated with new? Can I delete pointers allocated with malloc](http://www.parashift.com/c++-faq-lite/mixing-malloc-and-delete.html)(c++-faq-lite) – eerorika Mar 14 '14 at 13:28
  • In the case of an array of `double`s, it is "mostly safe" in practice, although it is of course still _wrong_ and invokes UB. I'm saying "mostly" because in practice the operators new and delete simply wrap malloc and free, plus calling constructors and destructors. Destructors on `double` are trivial, so no difference there. But of course you are _not guaranteed_ that `malloc` and `free` are used in your implementation... it _might_ be something else too. Preferrably a library would offer a function to allocate and unallocate stuff (wrapping whichever is correct). No such thing there? – Damon Mar 14 '14 at 13:41
  • Generally, it's bad practice to release memory allocated by another module. The responsability of allocating/deallocating memory should be either of the caller or the callee. The idea behind this is that if you have those modules linked against different CRTs you are basically allocation memory on one heap and trying to deallocate it on another heap. This happens when the modules link statically against the CRT. – Alin Mar 14 '14 at 13:46
  • To quote C++ faq: `It is illegal, immoral, and despicable to call free() with a pointer allocated via new, or to call delete on a pointer allocated via malloc()` – Arjun Sreedharan Mar 14 '14 at 13:59

6 Answers6

19

You MUST match calls to malloc with free and new with delete. Mixing/matching them is not an option.

edtheprogrammerguy
  • 5,957
  • 6
  • 28
  • 47
8

You are not allowed to mix and match malloc and free with new and delete the draft C++ standard refers back to the C99 standard for this and if we go to the draft C++ standard section 20.6.13 C library it says (emphasis mine going forward):

The contents are the same as the Standard C library header stdlib.h, with the following changes:

and:

The functions calloc(), malloc(), and realloc() do not attempt to allocate storage by calling ::operator new() (18.6).

and:

The function free() does not attempt to deallocate storage by calling ::operator delete(). See also: ISO C Clause 7.11.2.

and includes other changes, none of which state that we can use free on contents allocated with new. So section 7.20.3.2 The free function from the draft C99 standard is still the proper reference and it says:

Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
3

As you've heard now, you can't mix them.

Keep in mind that in C++ it's common to have lots of relatively small temporary objects dynamically allocated (for instance, it's easy to write code like my_string + ' ' + your_string + '\n'), while in C memory allocation's typically more deliberate, often with a larger average allocation size and longer lifetime (much more likely someone would directly malloc(strlen(my_string) + strlen(your_string) + 3) for the result without any temporary buffers). For that reason, some C++ libraries will optimise for large numbers of small transient objects. They might, for instance, use malloc() to get three 16k blocks, then use each for fixed-size requests of up to 16, 32 and 64 bytes respectively. If you call delete in such a situation, it doesn't free anything - it just returns the particular entry in the 16k buffer to a C++-library free list. If you called free() and the pointer happened to be to the first element in the 16k buffer, you'd accidentally deallocate all the elements; if it wasn't to the first you have undefined behaviour (but some implementations like Visual C++ apparently still free blocks given a pointer anywhere inside them).

So - really, really don't do it.

Even if it ostensibly works on your current system, it's a bomb waiting to go off. Different runtime behaviour (based on different inputs, thread race conditions etc.) could cause a later failure. Compilation with different optimisation flags, compiler version, OS etc. could all break it at any time.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
1

The library should really provide a deallocation function that forwards to the correct function.

In addition to what the others already said (no compatibility guarantee), there is also the possibility that the library is linked to a different C library than your program, and so invoking free() on a pointer received from them would pass it to the wrong deallocation function even if the function names are correct.

Simon Richter
  • 28,572
  • 1
  • 42
  • 64
0

You must use delete operator to deallocate memory when it is allocated by new operator.

haccks
  • 104,019
  • 25
  • 176
  • 264
0

malloc() allocates the memory and sends the address of the first block to the assigned pointer variable,in the case of new it allocates the memory and returns the address .it is a convention that when you use a malloc() function we should use delete function and when you are allocating memory with the help of new function the usage of free() function is comfortable.when malloc()it is a convention that we should use the corresponding realloc(),calloc(),delete() functions and similarly,when you use new() function the corresponding free()function is used.