跟踪对象和引用

时间:2013-02-27 23:05:26

标签: c++

如果我们注释掉下面强调的行,我们会在控制台中获得777。 否则我们得到一些垃圾(-534532345)。 我的环境是Microsoft Visual Studio 2012 Pro。

class C
{
public:
    C () { x = 777; }
    void ou() {cout << x;}
protected:
    int x;
};

class A
{
public:
    A(C & rrc) : rc(rrc) {};
    void koo () {rc.ou();}
protected:
    C & rc;
};

int _tmain(int argc, _TCHAR* argv[])
{
    C c;
    C * pc = new C;
    A a(*pc);
    delete pc; // <<<< this line
    a.koo();

    return 0;
}

任何人都可以帮我弄清楚为什么我会看到这种行为吗?

4 个答案:

答案 0 :(得分:7)

在您调用a.koo()时,您已删除其rc引用所引用的基础对象。那当然是UB。接下来发生的事情可能是在给定平台上针对给定编译具有一致行为,甚至可能输出777(实际上,由于基础对象最近被删除,可能会输出777)。在您的情况下,似乎先前已分配给_tmain()的pc对象的内存已被重新分配给已覆盖它的其他内容,或者您​​正在使用其内存分配器的调试版本显式地用一些固定值覆盖已删除/释放的内存,通常是非零而不是全部,但是可以识别的东西,如0xAAAAAAAA或0xDEADDEAD。由于-534532345是0xE023AF07(或0xFFFFFFFFE023AF07),我猜它是前者(内存已被分配给其他覆盖它的东西)。由于你的示例中对a.koo()的调用紧跟在delete pc之后,我发现令人惊讶的是它已经很快被覆盖了,但技术上任何事都可能,因为它是UB。

答案 1 :(得分:4)

删除会留下您所遵循的悬空引用,从而导致未定义的行为。它不是C ++或MS VS中的漏洞。该语言允许许多非法操作未经检查,并让程序员不要调用UB。

答案 2 :(得分:4)

代码具有未定义的行为。您持有不再存在的对象的引用。因此,rc.ou()行为未定义。

答案 3 :(得分:1)

如果你删除pc,那么A :: rc将指向垃圾位置和rc.ou();也将输出垃圾。这是预期的行为,无论您使用何种编译器,它都会执行此操作

Btw 99 [.99]%你认为你在编译器中发现了一个bug,这真的是你的错误