=======================
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
The reference is from a destructor of a derived class.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.
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
This is class TestCasepcmattman wrote:What does the function look like? Can you post some code?
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 */
I would highly suggest not letting the compiler generate anything for you when you're writing a kernelTestFramework doesn't have a destructor (of course, g++ generated one for me).
You mean I should implement an empty destructor for TestFramwork? I'll try tonight.pcmattman wrote:I would highly suggest not letting the compiler generate anything for you when you're writing a kernelTestFramework doesn't have a destructor (of course, g++ generated one for me).
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)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.
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.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.
Uh, sorry, I was talking about compilers.Colonel Kernel wrote:Visual C++ compiler back in 2003...
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++: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:
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)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.
The only way to "fix" this is to use a compiler that uses a different ABI
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 ? */
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.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.
Most likely because it'll remove the unused functionality.btw: when switch -O2 is used the reference to operator delete will disappear