3

几天来我们一直在调试一个奇怪的案例,并在一定程度上隔离了这个错误,但它仍然没有任何意义。也许这里的任何人都可以给我一个关于发生了什么的线索。

问题是发生在部分代码中的访问冲突。

基本上我们有这样的东西:

void aclass::somefunc() {
  try {
    erroneous_member_function(*someptr);
  } 
  catch (AnException) {
  }
}

void aclass::erroneous_member_function(const SomeObject& ref) {
  // { //<--scope here error goes away
  LargeObject obj = Singleton()->Object.someLargeObj; //<-remove this error goes away

  //DummyDestruct dummy1//<-- this is not destroyed before the unreachable

  throw AnException();

  // } //<--end scope here error goes away 

  UnreachableClass unreachable; //<- remove this, and the error goes away

  DummyDestruct dummy2; //<- destructor of this object is called! 
}

在调试器中,它实际上看起来像是在破坏 UnreachableClass,并且当我插入 DummyDestruct 对象时,它不会在调用奇怪的析构函数之前被破坏。因此,LargeObject 的破坏似乎并没有出错。

所有这些都在生产代码的中间,很难将其隔离为一个小示例。

我的问题是,有没有人知道是什么原因造成的,发生了什么?我有一个功能齐全的调试器(Embarcadero RAD 工作室),但现在我不确定如何处理它。

谁能给我一些关于如何进行的建议?

更新:

我在 throw 子句下方放置了一个 DummyDestruct 对象,并在析构函数中放置了一个断点。输入了这个对象的析构函数(只有我们在这段代码中)。

4

5 回答 5

1

根据您提供的信息,如果一切都如您所说,唯一可能的答案是编译器/优化器中的错误。只需添加带有注释的额外范围(这也是,如果一切都与您所说的完全一样)。

于 2010-02-24T13:26:05.520 回答
1

由于通过未初始化的指针写入、超出范围的数组访问等,有时会发生这种情况。导致错误的点可能会从它出现的地方完全移除。但是,根据您描述的症状,它似乎已定位在此功能中。复制构造函数LargeObject会行为不端吗?正在使用 ref 吗?也许somePtr没有指向有效的SomeObject. 是否Singleton()返回指向有效对象的指针?编译器错误也是可能的,尤其是在开启积极优化的情况下。我会尝试重新创建没有优化的错误。

于 2010-02-24T13:56:36.663 回答
1

是时候练习我的心灵感应调试技能了:

我最好的猜测是您的应用程序存在堆栈损坏错误。这可能会在调用堆栈上写入垃圾,这意味着调试器在您中断时错误地报告了该函数,并且它实际上不在析构函数中。要么,要么您错误地解释了调试器的信息,并且对象确实被正确地破坏了,但是您不知道为什么!

如果堆栈损坏是这种情况,您将很难找出根本原因是什么。这就是为什么在整个程序中实现大量诊断(例如断言)很重要的原因,这样您就可以在堆栈损坏发生时捕获它,而不是陷入其奇怪的副作用。

于 2010-02-24T13:57:28.690 回答
0

这可能是一个真正的长镜头,但无论如何我都会把它放在那里......

你说你使用 borland - 什么版本?你说你在一个字符串中看到错误 - STL?你的项目中是否包含winsock2?

我问的原因是我在使用 borland 6 (2002) 和 winsock 时遇到了问题 - 标题似乎弄乱了结构打包,这意味着不同的翻译单元对 std::string 的内存布局有不同的想法,具体取决于翻译单元包含了哪些标题,结果可想而知是灾难性的。

于 2010-02-24T14:02:05.233 回答
0

这是另一个疯狂的猜测,因为您提到了字符串。我知道至少一种实现,其中(STL)字符串复制是以惰性方式完成的(即,在进行更改之前不会实际复制字符串内容;“复制”是通过简单地拥有目标字符串对象来完成的指向与源相同的缓冲区)。在那个特定的实现(GNU)中存在一个错误,即过度复制会导致引用计数器(有多少对象在复制后使用相同的实际字符串内存)翻转到 0,从而导致各种恶作剧。我自己没有遇到过这个错误,但有人告诉过我。(我这么说是因为人们会认为 ref 计数器将是一个 32 位的数字,并且至少可以说,它翻滚的机会非常渺茫,

于 2010-02-24T14:11:32.857 回答