std::string custom operator new/delete function
This is an issue which really would have been better to raise on the mailing list, where it would be visible to a broader spectrum of experienced users. My own expertise is predominantly in FORTRAN-77 and C programming; my knowledge of C++ is sketchy, at best. Nonetheless, I will try to answer, to the best of my ability.
Firstly, let me make it perfectly clear: any comparison between behaviour on Windows, and behaviour on Linux, is completely irrelevant; the two platforms are fundamentally different, and there are many pitfalls in migrating from either one to the other. In this case, I believe you are falling foul of one of those pitfalls; there is no bug here, beyond a gap in your understanding.
In your test case, while you define replacements for both new and delete, I see no explicit use of either; any use which does arise is implicit in the instantiation, and subsequent destruction, of the std::string object, to which you refer. Instantiation of that object, apparently, does invoke new, and destruction thus invokes delete, but consider this: where is the implementation of that std::string class object defined? I'll give you some time to think about that, then I'll suggest, in follow-up comments, how the answer may explain the behaviour you have observed.
Thank you for your reply.
It is possible that I am missing something. I understand that std::string can have own implementation of allocation of the data. I think that in the current libstdc++ implementation if a length of the string is greater than 15 bytes, then it uses the heap for allocation.
On line 43, there is an assignment operator for the string and this string is long enough to allocate string data on the heap. On the next line the object "obj" ends its lifetime so "obj" destructor is called, also with std::string destructor which releases the string data.
For me it is strange that there is no 1 to 1 relation between calling operator new/delete (how should I release memory that was not allocated in my allocator?). I tried other containers like std::vector and they seem to be consistent.
You need to think about it some more. You are correct, in your belief that new should be called ... indeed, it is, but it isn't your replacement that's even considered. Think about where the std::string implementation is, and what that implies for where it must find the implementation of new that it does call.
So, you think it is because the implementation of the std::string is in an external dll? It may explain that my operator new was not called.
Indeed, If I compile it with the "-static" linker option my operator new/delete is called. But why was my operator delete called? Is it because the compiler optimized the std::string destroy function to be inlined?
I am thinking about the experience that I had with std::vector - maybe it is because the std::vector is a template that is compiled with the source.
Reply To marvol
So, you think it is because the implementation of the std::string is in an external dll?
Yes ... in fact, I know it to be so.
It may explain that my operator new was not called.
It does. There is a fundamental, and significant, difference between the properties of ELF shared objects, as used on Linux, and the equivalent PE-coff DLLs, as used on Windows. Do you know what it is?
Indeed, If I compile it with the "-static" linker option my operator new/delete is called.
Actually, -static-libstdc++ is sufficient.
But why was my operator delete called? Is it because the compiler optimized the std::string destroy function to be inlined?
Yes. You can study the effect of differing optimization levels, by compiling with -S -o-, and examining the assembly output. At -O1 (and above), your Obj class object is optimized away, and your test function includes exactly one reference to a std::string method — likely a copy constructor — and then your delete operator code is called; at -O2 (and -O3) even the delete call is optimized away, and your code is in-lined. At no optimization level, is your new operator ever called, but it is likely that whatever new operator implementation std::string knows about is called, (by what I assume to be its cryptically named copy constructor). That, in itself, is disturbing, because you have a potentially incompatible new and delete pairing, at any optimization level of -O1 or above.
I am thinking about the experience that I had with std::vector - maybe it is because the std::vector is a template that is compiled with the source.
Maybe. You haven't shown me anything, which I might evaluate.
Reply To keith
Thank you for the explanation!
Maybe. You haven't shown me anything, which I might evaluate.
Actually, the code is similar, just include vector
and replace the "test" function:
My operator new/delete is called in all optimization levels.
Hello,
I am writing a custom wrapper for new/delete allocations to get an aligned memory. I noticed that if I use std::string, operator new/delete are not called as it is in a linux version of g++ (operators new/delete are called). With the default optimization level, operator new/delete is not called and with optimization levels O1, O2, O3 only operator delete is called.
Source:
Compiling with the default optimization level:
Output:
Compiling with the O2 optimization level:
Output:
I am using: