Page 1 of 1
A bug in g++?
Posted: Mon Aug 24, 2009 9:31 am
by torshie
Because my kernel heap does not work now, I never used new/delete in my code, all objects are static or auto. But I got a link error that says "undefined reference to operator delete(void*)". I didn't link my code against other standard library. How could the code generated by g++ wanted to call "operator delete(void*)" ? Any ideas?
=======================
Edit: After further investigation I find out that delete never get called, but I need to add a delete implementation in order to link my kernel. Don't know why
Thanks
torshie
Re: A bug in g++?
Posted: Mon Aug 24, 2009 9:40 am
by NickJohnson
Just because delete() is never used doesn't necessarily mean it is not referenced anywhere, afaik. Are you using -fno-builtin?
Also, did you check which function was doing the reference? The linker should spit out the name of the previous symbol if there's an error.
Re: A bug in g++?
Posted: Mon Aug 24, 2009 9:43 am
by torshie
NickJohnson wrote:Just because delete() is never used doesn't necessarily mean it is not referenced anywhere, afaik. Are you using -fno-builtin?
Also, did you check which function was doing the reference? The linker should spit out the name of the previous symbol if there's an error.
The reference is from a destructor of a derived class.
Just tried, add option -fno-builtin makes no difference.
Re: A bug in g++?
Posted: Mon Aug 24, 2009 10:00 am
by torshie
Just disassembled the binary. But still don't know why operator delete is needed.
Code: Select all
ffffff00001075c4 <kernel::TestFramework::~TestFramework()>:
ffffff00001075c4: 48 83 ec 18 sub $0x18,%rsp
ffffff00001075c8: 48 89 7c 24 08 mov %rdi,0x8(%rsp)
ffffff00001075cd: 48 8b 44 24 08 mov 0x8(%rsp),%rax
ffffff00001075d2: 48 ba 90 7a 10 00 00 mov $0xffffff0000107a90,%rdx /* vtable for TestFramework */
ffffff00001075d9: ff ff ff
ffffff00001075dc: 48 89 10 mov %rdx,(%rax)
ffffff00001075df: 48 8b 44 24 08 mov 0x8(%rsp),%rax
ffffff00001075e4: 48 89 c7 mov %rax,%rdi
ffffff00001075e7: 48 b8 7a 73 10 00 00 mov $0xffffff000010737a,%rax /* destructor of TestCase which is TestFramework's super class */
ffffff00001075ee: ff ff ff
ffffff00001075f1: ff d0 callq *%rax
ffffff00001075f3: b8 00 00 00 00 mov $0x0,%eax
ffffff00001075f8: 84 c0 test %al,%al
ffffff00001075fa: 74 14 je ffffff0000107610 <kernel::TestFramework::~TestFramework()+0x4c>
ffffff00001075fc: 48 8b 44 24 08 mov 0x8(%rsp),%rax
ffffff0000107601: 48 89 c7 mov %rax,%rdi
ffffff0000107604: 48 b8 b1 5f 10 00 00 mov $0xffffff0000105fb1,%rax /* This is operator delete() */
ffffff000010760b: ff ff ff
ffffff000010760e: ff d0 callq *%rax
ffffff0000107610: 48 83 c4 18 add $0x18,%rsp
ffffff0000107614: c3 retq
Re: A bug in g++?
Posted: Mon Aug 24, 2009 3:39 pm
by pcmattman
What does the function look like? Can you post some code?
Re: A bug in g++?
Posted: Mon Aug 24, 2009 7:42 pm
by torshie
pcmattman wrote:What does the function look like? Can you post some code?
This is class TestCase
Code: Select all
namespace kernel {
class TestCase {
public:
virtual void setup();
virtual void tearDown();
virtual void addTestPoint();
protected:
TestCase();
virtual ~TestCase() {}
private:
TestCase(const TestCase&);
const TestCase& operator=(const TestCase&);
};
} /* namespace kernel */
class TestFramework is derived from TestCase and TestFramework doesn't have a destructor (of course, g++ generated one for me).
In order to make debugging easier, compiler option -O0 -g was used.
Re: A bug in g++?
Posted: Mon Aug 24, 2009 7:45 pm
by pcmattman
TestFramework doesn't have a destructor (of course, g++ generated one for me).
I would highly suggest not letting the compiler generate
anything for you when you're writing a kernel
Re: A bug in g++?
Posted: Mon Aug 24, 2009 8:26 pm
by torshie
pcmattman wrote:TestFramework doesn't have a destructor (of course, g++ generated one for me).
I would highly suggest not letting the compiler generate
anything for you when you're writing a kernel
You mean I should implement an empty destructor for TestFramwork? I'll try tonight.
Re: A bug in g++?
Posted: Tue Aug 25, 2009 11:11 pm
by froggey
You must implement operator delete, even if it's just panic("Can't happen!"), it's required by the C++ ABI. Every class gets 3 destructors:
base object destructor of a class T: A function that runs the destructors for non-static data members of T and non-virtual direct base classes of T.
complete object destructor of a class T: A function that, in addition to the actions required of a base object destructor, runs the destructors for the virtual base classes of T.
deleting destructor of a class T: A function that, in addition to the actions required of a complete object destructor, calls the appropriate deallocation function (i.e,. operator delete) for T.
http://www.codesourcery.com/public/cxx-abi/abi.html (I know it says "Itanium C++ ABI", but it's the same ABI that gcc uses on x86)
The only way to "fix" this is to use a compiler that uses a different ABI
Re: A bug in g++?
Posted: Tue Aug 25, 2009 11:44 pm
by Solar
...or not using virtual functions / inheritance in kernel space.
Regarding the thread title - the chance of any of us actually finding a bug in a well-used toolchain is very, very slim. For all practical purposes, I would not consider that possibility when looking for the cause of unexpected behaviour.
Re: A bug in g++?
Posted: Wed Aug 26, 2009 12:48 am
by Colonel Kernel
Solar wrote:...or not using virtual functions / inheritance in kernel space.
Regarding the thread title - the chance of any of us actually finding a bug in a well-used toolchain is very, very slim. For all practical purposes, I would not consider that possibility when looking for the cause of unexpected behaviour.
I found at least three bugs in the Visual C++ compiler back in 2003, just by trying to compile some crazy template-heavy code (using Loki and deeply nested typelists). I reported them to Microsoft too.
So, it does happen, just not very often.
Re: A bug in g++?
Posted: Wed Aug 26, 2009 1:12 am
by Solar
Colonel Kernel wrote:Visual C++ compiler back in 2003...
Uh, sorry, I was talking about
compilers.
Of course it does happen. I was pretty amazed when my problems with some code in the office turned out to be a bug in the Boost libraries that's been lurking around for ages (v1.33 through v1.39).
It's just that you shouldn't think too much about this possibility when searching for the cause of your problems. I'd say the own-bug vs. toolchain-bug ratio to be around 10.000 : 1.
Re: A bug in g++?
Posted: Wed Aug 26, 2009 6:55 am
by torshie
froggey wrote:You must implement operator delete, even if it's just panic("Can't happen!"), it's required by the C++ ABI. Every class gets 3 destructors:
base object destructor of a class T: A function that runs the destructors for non-static data members of T and non-virtual direct base classes of T.
complete object destructor of a class T: A function that, in addition to the actions required of a base object destructor, runs the destructors for the virtual base classes of T.
deleting destructor of a class T: A function that, in addition to the actions required of a complete object destructor, calls the appropriate deallocation function (i.e,. operator delete) for T.
http://www.codesourcery.com/public/cxx-abi/abi.html (I know it says "Itanium C++ ABI", but it's the same ABI that gcc uses on x86)
The only way to "fix" this is to use a compiler that uses a different ABI
The deallocation function must not be operator delete, since I don't call operator new(code generated by g++ doesn't either). Only need to change %rsp to deallocate the memory. Look at the code generated by g++:
Code: Select all
ffffff00001075f3: b8 00 00 00 00 mov $0x0,%eax
ffffff00001075f8: 84 c0 test %al,%al
ffffff00001075fa: 74 14 je ffffff0000107610 <kernel::TestFramework::~TestFramework()+0x4c>
ffffff00001075fc: 48 8b 44 24 08 mov 0x8(%rsp),%rax
ffffff0000107601: 48 89 c7 mov %rax,%rdi
ffffff0000107604: 48 b8 b1 5f 10 00 00 mov $0xffffff0000105fb1,%rax /* This is operator delete() */
ffffff000010760b: ff ff ff
ffffff000010760e: ff d0 callq *%rax /* How could it be possible that we reach here ? */
How could it be possible that operator delete get called? This is what makes me confused. g++ generates code that unnecessarily depends on an operator delete() implementation. Maybe this is just a feature, not a bug.
btw: when switch -O2 is used the reference to operator delete will disappear.
Re: A bug in g++?
Posted: Wed Aug 26, 2009 4:18 pm
by pcmattman
How could it be possible that operator delete get called? This is what makes me confused. g++ generates code that unnecessarily depends on an operator delete() implementation. Maybe this is just a feature, not a bug.
Because it's part of the ABI for each class to have the three destructors, as froggey has already mentioned. The deleting constructor does depend on operator delete, which is the C++ way to delete memory. It doesn't matter whether or not you've actually allocated the memory with new; the compiler picks the right constructor every time.
btw: when switch -O2 is used the reference to operator delete will disappear
Most likely because it'll remove the unused functionality.