Wrong operator delete called in Release mode (with VS2008)

Wrong operator delete called in Release mode (with VS2008)

Hello.

I am using Intel C++ compiler with Visual Studio 2008. When I override the new/delete operators I get a strange behaviour for a very simple program.I simply override the new/delete operators and then I create a string object.

The problem is that when I use Intel C++ in Release mode, my operator new is not called BUT my operator delete is called. This means that the application crashes because I do a scalable_free but the system had done a normal malloc.

This does not happen in Intel C++ Debug mode or in MS C++ (Debug or Release mode).

Here is the test program:

#include "tbbscalable_allocator.h"
#include 
#include 
using namespace std;

void* operator new (size_t size) throw (std::bad_alloc)
{
	cout << "Called my new" << endl;
	if (size == 0) size = 1;
	if (void* ptr = scalable_malloc(size)) return ptr;
	throw std::bad_alloc();
}

void* operator new[] (size_t size) throw (std::bad_alloc)
{
	cout << "Called my new[]" << endl;
	return operator new (size);
}

void operator delete (void* ptr) throw ()
{
	cout << "Called my delete" << endl;
	if (ptr != 0) scalable_free(ptr);
}

void operator delete[] (void* ptr) throw()
{
	cout << "Called my delete[]" << endl;
	operator delete (ptr);
}

// I omit the non-throwing versions, but they exist

int main() 
{
	string str("A test string. A test string.");
	return 0;
}

The output of the program with Intel C++ Release: is "Called my delete" (and a crash) while the output in Debug mode and in MS C++ is none (meaning that none of my operators is called).

Finally, if I disable the optimisations (/Od), I don't get the error.

Is this a bug in the Intel C++ compiler?

I would appreciate your comments and any workaround you can think of.

Thanks in advance

Alfredo

21 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Several questions.

1. what version of icl?
2. are you using TBB from the Intel C++ Compiler package? or you have downloaded a different version?
3. compile options?

Jennifer

Quoting - Jennifer Jiang (Intel)

Several questions.

1. what version of icl?
2. are you using TBB from the Intel C++ Compiler package? or you have downloaded a different version?
3. compile options?

Jennifer

Thanks for your prompt response and sorry for the missing data.

1. I am usingIntel C++ Compiler 11.1.061 [IA-32].

2. I use the TBB that comes with the compiler, but I think this is not related to TBB. It is related to the delete operator being called when it should not (no matter if the delete operator will call something in TBB or something else).

3. I am using Visual Studio to compile and its default settings, which are:

For compiling:
/c /Od /Oi /Qipo /I "C:Program FilesIntelParallel StudioComposerTBBInclude" /D "_MBCS" /EHsc /MD /GS /Gy /fp:fast /Fo"Release/" /W3 /nologo /Zi

For linking:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /OUT:"c:alfredoc++testsVC9intelTesttest2Releasetest2.exe" /nologo /LIBPATH:"C:Program FilesIntelParallel StudioComposerTBBia32vc9Lib" /MANIFEST /MANIFESTFILE:"Releasetest2.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /TLBID:1 /DEBUG /PDB:"c:alfredoc++testsVC9intelTesttest2Releasetest2.pdb" /OPT:REF /OPT:ICF /DYNAMICBASE /NXCOMPAT /IMPLIB:"c:alfredoc++testsVC9intelTesttest2Releasetest2.lib" /MACHINE:X86

Thanks

Alfredo

Quoting - aolivera123

For compiling:
/c /Od /Oi /Qipo /I "C:Program FilesIntelParallel StudioComposerTBBInclude" /D "_MBCS" /EHsc /MD /GS /Gy /fp:fast /Fo"Release/" /W3 /nologo /Zi

Note that the /Od setting is for the "working" version. Change it to /O2 to get the error.

It seems a bug related to /Qipo. Removing it the code called both "new" and "delete":

>>t_icl_Od.exe
>>
>>t_cl_Od.exe
>>
>>t_icl_o2.exe
Called my new
Called my delete
>>
>>t_cl_o2.exe
>>

This is better, but still not the same as cl.
I'll file two bug reports about this. one relaed to /Qipo, one about the compatibility. When this is fixed, I'll post a news here.
Thanks for your post and also a testcase.
Jennifer

Quoting - Jennifer Jiang (Intel)

I'll file two bug reports about this. one relaed to /Qipo, one about the compatibility. When this is fixed, I'll post a news here.

Thanks for the workaround, I will remove the /Qipo until the bug is fixed.

About the compatibility, I like that both my new and delete were called. In fact, this is the behaviour you get in gcc: if you overload them, they are called.

In any case, or you call both (gcc) or you call none (MS), but you cannot call one (the delete) and not the other (the new).

Thanks

It seems that with a slightly more complicated example the workaround does not work. Now I tried this (read a line from a file):

ifstream file ("Test.txt", std::ios_base::in);
string line;
getline(file, line, 'n');

With the following compiler settings:
/c /O2 /I "C:Program FilesIntelParallel StudioComposerTBBInclude" /D "_MBCS" /EHsc /MD /GS /Gy /fp:fast /Fo"Release/" /W3 /nologo /Zi

Just in case, here are my linker settings:
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /OUT:"c:alfredoc++testsVC9intelTesttest2Releasetest2.exe" /nologo /LIBPATH:"C:Program FilesIntelParallel StudioComposerTBBia32vc9Lib" /MANIFEST /MANIFESTFILE:"Releasetest2.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /TLBID:1 /DEBUG /PDB:"c:alfredoc++testsVC9intelTesttest2Releasetest2.pdb" /OPT:REF /OPT:ICF /DYNAMICBASE /NXCOMPAT /IMPLIB:"c:alfredoc++testsVC9intelTesttest2Releasetest2.lib" /MACHINE:X86

I attach a Test.txt which makes this fail.

And I get only my delete called. So, the same problem as the beggining. It seems that the only workaround is to disable all the optimisations.

Has anybody been able to redefine new/delete in a Windows environment with Intel C++ ?

Attachments: 

AttachmentSize
Downloadtext/plain Test.txt21 bytes

Try to disable inlining, maybe it will help. Such code worked for me before, will recheck and let you know.

Quoting - Igor Levicki
Try to disable inlining, maybe it will help. Such code worked for me before, will recheck and let you know.

If I do that it works, but the code is too slow (not the tiny sample I gave, but the real program). The MS compiler with the inlining enabled gives me better running time than Intel C++ with no inlining!

Quoting - aolivera123

If I do that it works, but the code is too slow (not the tiny sample I gave, but the real program). The MS compiler with the inlining enabled gives me better running time than Intel C++ with no inlining!

Then disable inlining just for that single function. D'oh!

Quoting - Igor Levicki

Then disable inlining just for that single function. D'oh!

Do you mean that I should disable inlining for my overloadede new/delete functions?

I didn't know that such thing could be done. Which compiler flag should I use?

The behavior of the Microsoft compiler depends solely on whether
or not the standard library is linked in dynamically or statically,
i.e. with /MDd the new/delete operators are not overridden but
with /MTd they are.

The Intel compiler behaviour depends both on dynamic/static linking
and whether certain optimizations like inlining are enabled.
With static linking (i.e. /MTd) our behavior is the same as
Microsoft's - the functions are overridden.

So perhaps an acceptable workaround would be to link in the
C++ standard library statically?

Quoting - aolivera123

Do you mean that I should disable inlining for my overloadede new/delete functions?

I didn't know that such thing could be done. Which compiler flag should I use?

Try adding __declspec(noinline) in front of the function definition.

Quoting - Judith Ward (Intel)

So perhaps an acceptable workaround would be to link in the
C++ standard library statically?

Thanks for the answer.

If I compile using MTd it works fine, but if I use MT I get a crash when the applications starts (not even executes the first line). Being a release version, I would not like to link with a debug version (MTd) of the runtime library.

Quoting - Igor Levicki

Try adding __declspec(noinline) in front of the function definition.

It did not work. Maybe it avoided inlining the new/delete but it inlined the callers...

Quoting - aolivera123

It did not work. Maybe it avoided inlining the new/delete but it inlined the callers...

Unfortunately sometimes it can help, and sometimes not like in your case. Hopefully it would be fixed soon.

This issue is being worked on. The coming Intel C++ Compiler for Windows update 5 will not contain the fix. Sorry about this.

I'm still waiting to see if it's possible to fix in the update after update 5. I'll let you know when there's more news.

Right now the work-around is to use the debug libs or use /Ob1.

Like:

C:\test\

>>icl /O2 /Ob1 /EHsc /MD new-t.cpp
Intel C++ Compiler Professional for applications running on IA-32, Version 11.1 Build 20091130 Package ID: w_cproc_p_11.1.054
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

new-t.cpp
Microsoft Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

-out:new-t.exe
new-t.obj

C:\test\
>>new-t.exe
Called my new
TEXT: This is a testing. ***
Called my delete

C:\test\

Thanks,

Jennifer

Attachments: 

AttachmentSize
Downloadtext/x-c++src new-t.cpp959 bytes

There's another work-around using "/Qinline_dllimport-", see below.

Both /Ob1 & this option may have performance impact.

C:\test
>>icl /O2 /Ob2 /EHsc /MD /Qinline_dllimport- new-t.cpp
Intel C++ Compiler Professional for applications running on IA-32, Version 11.1 Build 20091130 Package ID: w_cproc_p_11.1.054
Copyright (C) 1985-2009 Intel Corporation. All rights reserved.

new-t.cpp
Microsoft Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.

-out:new-t.exe
new-t.obj

C:\test
>>new-t
TEXT: This is a testing. ***

C:\test

>>

Jennifer

Hi Alfredo,
did you see my response on "March 8, 2010 10:25 AM PST"? I didn't get your response so checking again.

Also I posted a work-around on "February 12, 2010 7:49 AM PST".

Did you seethose responses? Could you let me know? We're unable to duplicate the crashwhen using/MD.

Thanks,
Jennifer

About this issue, after our compiler engineer's investigation, it is not something can be fixed in the compiler.

In the Windows environment, in a program that is built using DLLs, replacing global operators new and delete is at best a chancy operation, because a replacement new/delete that’s provided in one DLL (or the main program) doesn’t necessarily replace all the uses from other DLLs.

So it’s possible to allocate memory using an operator new from one DLL, then later try to deallocate that same piece of memory using an operator delete from a different DLL. If those different functions from different DLLs happen to use the different underlying memory allocation/deallocation scheme then the program is very likely to fail.

This problem is inherent in the Windows dynamic-linking model, and can occur with Microsoft’s compiler too.

Jennifer

C++ operators new and delete shouldn't be called in case of automatic allocation of the variable str of type string ( and in all similar cases! ):
...
string str("A test string. A test string.");
...
and a non-default constructor and a destructor ( possibly virtual ) will be called instead.

Leave a Comment

Please sign in to add a comment. Not a member? Join today