views:

360

answers:

8

In C++ using delete to free memory obtained with malloc() doesn't necessarily cause a program to blow up.

Do you guys think a warning or perhaps even an assertion failure should be produced if delete is used to free memory obtained using malloc()??

Why do you think that Stroustrup did not had this feature on C++?

+16  A: 

In C++ using delete to free memory obtained with malloc() doesn't necessarily cause a program to blow up.

No, but it does necessarily result in undefined behavior, which means that anything can happen, including the program blowing up or the program continuing to run in what appears to be a correct manner.

Do you guys think a warning or perhaps even an assertion failure should be produced if delete is used to free memory obtained using malloc()??

No. This is difficult, if not impossible, to check at compile time. Runtime checks are expensive, and in C++, you don't get what you don't pay for.

It might be a useful option to turn on while debugging, but really, the correct answer is just don't mix and match them. I've not once had trouble with this.

James McNellis
I know...but just curious why Stroustrup did not have a warning when we combine the two... is it because C++ is C or C is C++? Maybe he just wants to confuse us :)
EquinoX
@Alexander: Because runtime checks add overhead, and I don't want to waste CPU cycles every time I delete something, checking for some mistake that is really quite impossible in well-designed software (if a software project has a big problem with this, it's certainly misusing pointers).
James McNellis
Thanks James that is really a good answer, C++ does not want to waste CPU cycles :)
EquinoX
I can still argue though that the run time check could just be 1-2 instructions :D
EquinoX
@Alexander: Still. given the multitude of ways you can screw up memory management in C++ using the wrong function/operator to delete things seems the simplest mistake to avoid.
Billy ONeal
1-2 instructions, and an extra byte tacked onto every single heap allocation.
Dennis Zickefoose
@EquinoX: In C++ you will write `delete` or `free` a lot less than you think, if you use smart pointers, value objects and RAII. The kind of protection you do ask would be similar to adding a helmet in cars for the people who like to ride their head outside the window...
paercebal
+1  A: 

A warning would be nice, but this probably does not happen because C++ was originally built upon C, so a runtime error could not be generated because malloc is valid C.

Its still extremely bad practice to do this, even if your program does not crash...

Justin Ethier
+4  A: 

delete has a special property that free() does not: it calls destructors, which in turn may call more deletes as that object may have allocated other things on the heap.

That said, new also calls the object's constructor, while malloc() does not. Don't mix these things unless you're absolutely sure you know what you're doing (and if you did, you wouldn't mix these things anyway).

a stray cat
I do understand the uses of malloc free new and delete... just curious on why it doesn't generate a warning when the wrong combinations are used
EquinoX
Because there's no way to tell. That pointer could have come from anywhere, you could have cast it from something else. The compiler can't know this at compile time.
a stray cat
@a stray cat: The compiler probably can't tell in the general case, but it can probably tell in the vast majority of cases.
Billy ONeal
The cases it can tell in are pretty trivial. If there are enough cases for there to be a vast majority, I have to wonder if they occur from somebody mismatching the calls within a function [the only situation I can imagine being reliably caught]. Calls like `make_shared(malloc(n))` are probably much more common, but also much more difficult for the compiler to help with.
Dennis Zickefoose
A: 

I don't know why compilers don't seem to do this, it seems to be useful.

The compiler could certainly associate a bit of data with each pointer saying (allocated with new or allocated with malloc, or unknown) and when it found a free or a delete if the allocation didn't match it could issue a warning. There would be no overhead with doing this at run time. It wouldn't catch all mistakes but it would catch some so be useful.

At run time, the c++ runtime already puts in lots of extra information on some compilers to catch buffer overruns and so on in debug builds so I don't see why it couldnd't add a flag to a memory block to say how it was allocated and somehow report an error if it fails.

I suppose the real answer is that it would actually catch many bugs at all. There seems to be an awful lot of questions on here with a new one every day about mixing new and malloc, and yet in 10 years of programming I've never seen a program that does it. C programs use malloc, c++ programs use new and I've almost never seen them mixed. If you are using C++ you just use new for everything. I guess there is legacy code out there that was originally C an has been reused in c++ but I doubt there is enough of that for this to be a big issue in real life.

Has anyone ever had a problem with this in a real program anyway?

John Burton
while analysing a version of the chromium source code we found some memory that was created with calloc was freed using delete. It has been fixed. Did it cause any errors? maybe, we didn't dig deep enough into the code to see if it actually caused any problems.
barkmadley
A: 

In C++ using delete to free memory obtained with malloc() doesn't necessarily cause a program to blow up.

You should never do that. Although some compiler allocate memory for new using malloc, free() doesn't call destructors. So if you mix "new" with "free" you'll get memory leaks, and a lot of hard to deal with problems. Just forget it. It isn't worth the effort.

Do you guys think a warning or perhaps even an assertion failure should be produced if delete is used to free memory obtained using malloc()??

As far as I know, on MSVC trying to delete() memory allocated with malloc generates debug error (something like "pCrtBlock is not valid", although I don't remember exact message). That is - if project was built with debug crt libraries. Happens because debug new() allocates extra memory for every allocated block and this block doesn't exist in memory allocated with malloc.

Why do you think that Stroustrup did not had this feature on C++?

In my opinion, because a programmer should be allowed to shoot himself in the foot with rocket launcher, if he really wants to do that. delete() isn't even supposed to be compatible with malloc, so adding protection against total stupidity isn't worth the effort of making a feature.

SigTerm
A: 

No.

When programming a compiler, warnings are the second hardest thing to develop.

Therefore, you usually have warnings against important thigns, as in "something that could really happen to a professional", not in a vast variety of a completely dumb misuse of the APIs. Besides, malloc and new allocated pointers may be impossible to distinguish at compile time.

Pavel Radzivilovsky
A: 

Personally the undefined behaviour of mixing and matching memory allocations schemes makes it undesirable to even mix them within the same program/library.

There are some static analysis tools that can identify this kind of memory allocation / deallocation imbalance and generate warnings for you. However static analysis is never 100% accurate or fool-proof, as there will always be limitations in the tools ability to track variables and memory locations in the program.

Full disclosure: I work at Red Lizard Software writing the goanna static analysis tool for C/C++ and it is capable of detecting this kind of mismatch in some, not all instances.

barkmadley
A: 

No. A warning cannot be produced because it is not possible to determine whether a pointer was assigned a piece of memory from malloc, new or is just pointing somewhere at compile time.

An assertion is a nice feature and so would array bound checking, NULL pointer checks, etc.., but C++ is an unmanaged programming language and assumes you know what you are doing.

5ound