A bug in g++?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

A bug in g++?

Post 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
Last edited by torshie on Mon Aug 24, 2009 9:41 am, edited 1 time in total.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: A bug in g++?

Post 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.
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: A bug in g++?

Post 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.
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: A bug in g++?

Post 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   
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: A bug in g++?

Post by pcmattman »

What does the function look like? Can you post some code?
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: A bug in g++?

Post 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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: A bug in g++?

Post 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 ;)
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: A bug in g++?

Post 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.
froggey
Member
Member
Posts: 38
Joined: Tue Oct 17, 2006 10:21 pm
Location: Hampshire, UK

Re: A bug in g++?

Post 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
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: A bug in g++?

Post 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.
Every good solution is obvious once you've found it.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re: A bug in g++?

Post 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.
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: A bug in g++?

Post by Solar »

Colonel Kernel wrote:Visual C++ compiler back in 2003...
Uh, sorry, I was talking about compilers. :twisted:

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.
Every good solution is obvious once you've found it.
torshie
Member
Member
Posts: 89
Joined: Sun Jan 11, 2009 7:41 pm

Re: A bug in g++?

Post 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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: A bug in g++?

Post 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.
Post Reply