Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7944 Discussions

Wrong operator delete called in Release mode (with VS2008)

aolivera123
Beginner
1,231 Views
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:
[cpp]#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;
}
[/cpp]
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

0 Kudos
20 Replies
JenniferJ
Moderator
1,212 Views
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
0 Kudos
aolivera123
Beginner
1,212 Views
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

0 Kudos
aolivera123
Beginner
1,212 Views
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.

0 Kudos
JenniferJ
Moderator
1,212 Views
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

0 Kudos
aolivera123
Beginner
1,212 Views
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

0 Kudos
aolivera123
Beginner
1,212 Views
It seems that with a slightly more complicated example the workaround does not work. Now I tried this (read a line from a file):
[cpp]ifstream file ("Test.txt", std::ios_base::in);
string line;
getline(file, line, 'n');
[/cpp]
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++ ?

0 Kudos
levicki
Valued Contributor I
1,212 Views
Try to disable inlining, maybe it will help. Such code worked for me before, will recheck and let you know.
0 Kudos
aolivera123
Beginner
1,212 Views
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!

0 Kudos
levicki
Valued Contributor I
1,212 Views
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!
0 Kudos
aolivera123
Beginner
1,212 Views
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?

0 Kudos
Judith_W_Intel
Employee
1,212 Views

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?
0 Kudos
levicki
Valued Contributor I
1,212 Views
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.
0 Kudos
aolivera123
Beginner
1,212 Views

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.

0 Kudos
aolivera123
Beginner
1,212 Views
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...

0 Kudos
levicki
Valued Contributor I
1,212 Views
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.
0 Kudos
JenniferJ
Moderator
1,212 Views

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

0 Kudos
JenniferJ
Moderator
1,212 Views

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

0 Kudos
JenniferJ
Moderator
1,212 Views
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
0 Kudos
JenniferJ
Moderator
1,212 Views

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

0 Kudos
SergeyKostrov
Valued Contributor II
1,031 Views
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.
0 Kudos
Reply