破坏后C ++的行为

时间:2009-09-25 12:41:01

标签: c++

我有一个从套接字读取的对象,如下所示:

void CSocketReader::ReadComplete ( )
{
 messageProcessor->ResponseReceived ( response );
 read ();
}

void CSocketReader::read()
{
 socket.read(response);
}

我的问题是,根据响应和我正在执行的协议,ResponseReceived方法可能导致删除CSocketReader对象。当ResponseReceived方法返回该指针所指向的对象时,该指针将被删除(但由于某些原因我不知道这个指针即使被删除后也不是NULL!)。接下来执行read方法,程序在读取内崩溃。如何可靠地检测到已在对象上执行的方法已被删除。

请帮忙。

6 个答案:

答案 0 :(得分:8)

在C ++标准中未定义对象被破坏后this指针的值是什么,因此this不是NULL也不足为奇 - 不需要C ++就可以将它设置为NULL

如果messageProcessor对象破坏了调用它的CSocketReader对象,那么程序的设计有点令人讨厌。至少我会使ResponseReceived函数返回bool true,如果它已删除了CSocketReader,那么你可以这样做:

if (!messageProcessor->ResponseReceived(response)) {
    return;
}

马上回来。但即使这可能也不安全;你不应该以一种可以在被破坏的对象上执行代码的方式构建你的程序。

答案 1 :(得分:4)

  

如何可靠地检测到已在对象上执行的方法已被删除。

你不能在对象本身内部设置'bool amDeleted'标志(因为在删除之后,标志/内存可能被其他东西重用/覆盖)。

唯一可行的方法(我能想到的)就像这样......

class Foo
{
  //have a static set of all valid Foo instance pointers
  typedef std::set<Foo*> Set;
  static Set s_set;

public:
  Foo()
  {
    s_set.insert(this);
  }

  //ditto in every other Foo constructor, including the copy constructor

  ~Foo()
  {
    s_set.remove(this);
  }

private:
  static bool exists(Foo* foo)
  {
    return s_set.find(foo) != s_set.end();
  }
};

[...或线程安全的Set如果Foo正在构建/运行/销毁多个线程]。

答案 2 :(得分:2)

删除对象不会更改指向该对象的指针。实现它需要每个对象“知道”它的所有指针,因此它可以在它的析构函数中将它们全部设置为NULL。如果它甚至可以实现,那将是性能和记忆的噩梦。对于不总是需要的功能,它肯定会花费很大的复杂性。 C ++避开那种类型的设计,宁愿不“强迫”你为你不需要的功能付费。

一个修复可能是不删除对象,但可能只是设置一个标记“deleteMe”,然后可以在您知道不再访问该对象时进行检查。

答案 3 :(得分:0)

你做不到。无法知道您正在处理已删除的对象。每当您尝试访问该已删除对象的成员变量时,行为都是未定义的。

答案 4 :(得分:0)

删除对象不会将其值设置为零 - 它只运行析构函数,并释放内存。如果messageProcessor-&gt; ResponseReceived(响应);函数可能会删除调用该函数的对象的实例,那么你就遇到了麻烦 - 返回时该指针的值将保持不变(C ++不会为你重写调用堆栈),但你现在在未定义的行为土地。此外,其他保持指向此对象的指针仍将指向对象所在的内存,因为无法找到所有引用并重写它们 - 指针只是一个被解释为地址的存储值。

最简单的解决方案是使用messageProcessor-&gt; ResponseReceived(响应);返回一个标志,指示是否应该继续 - 如果没有,立即退回并返回。更好的解决方案可能是重新设计以避免这种情况。

答案 5 :(得分:0)

删除指针后,它不会自动返回null。如果需要,应将其显式设置为null。

当一个方法调用一个不再存在的类时,除非你使用它的一个属性或字段,否则什么都不会发生。所以代码可能仍然没有问题。

因此,前几行可以插入一些代码来检查this指针是否仍然是有效的。 (例如,您可以使用包含所有有效实例指针的静态hashmap来检查这一点)。如果您检测到此指针不再有效,请退出方法