2016-08-12 56 views
1

我的C的简化版本++类:显式析构函数调用不工作

我的单元测试的
class Class 
{ 
public: 
    Class(uint32_t size_, uint8_t val_) buf(NULL), size(size_) 
    { 
     buf = new uint8_t[size]; 
     memset(buf, val_, size); 
    } 
    ~Class() 
    { 
     if(buf != NULL) 
     { 
      delete[] buf; 
      buf = NULL; 
      size = 0; 
     } 
    } 
    void FakeDtor() 
    { 
     if(buf != NULL) 
     { 
      delete[] buf; 
      buf = NULL; 
      size = 0; 
     } 
    } 

    protected: 
     uint8_t* buf; 
     uint32_t size; 
} 

代码:

TEST_F(Classtest, testDestructor) 
{ 
    Class *buff = new Class(10,10); 
    ASSERT_NE(buff->getData(), (uint8_t*)NULL); 

    buff->~Class(); // buff->FakeDtor(); 

    ASSERT_EQ(buff->getData(), (uint8_t*)NULL); 
} 

当我使用的MSBuild编译代码并运行UT - 显式调用析构函数工程和UT通行证。当我使用g ++编译并使用gtest运行UT时 - 显式调用dtor似乎失败了,因为在断言失败后。当我使用FakeDtor()而不是〜Class()时,UT在Windows和Linuix上同时通过。当在Linux下调用它时,什么会导致dtor不执行?

+0

你不能直接调用析构函数。 如果你不想销毁该对象使用'删除' –

+0

@JonasJuffinger是的,你可以。但你通常不应该。 –

+0

@JonasJuffinger:允许手动调用析构函数。这是一种正常的操作,特别是如果您使用new-at操作符来创建对象。 – Klaus

回答

2

在其非平凡的析构函数运行后,读取类的内容会调用未定义的行为。对象所在的内存仍然存在并不重要,因为你没有对象,对象本身已经死了,不能再使用。

从字面上看,一切都可以发生,如果你反正做。这个概念类似于悬挂指针/参考,例如参见this

这个UB包含“如果析构函数设置数据成员值,由于没有有效的程序将永远无法读取这些值,编译器可以优化这些成员的设置。,正如@hvd在他的comment中指出的那样。

+1

其中,由于OP对于OP而言可能并不明显,这意味着如果析构函数设置了数据成员值,由于没有有效的程序将永远无法读取这些值,编译器可以优化这些成员的设置。 – hvd

+0

@ hvd:在一个实际上处于破坏状态的对象中操纵数据的意义是什么? – Klaus

+0

@Klaus这些操作的所有可观察的副作用都必须发生。尽管分配给内置类型没有副作用,但总是多余的。 –