在堆栈上创建对象之前可以展开对象吗?

发布于 2024-08-22 23:35:31 字数 1143 浏览 9 评论 0原文

我们已经调试一个奇怪的案例几天了,并在一定程度上隔离了该错误,但它仍然没有任何意义。也许这里的任何人都可以告诉我发生了什么事。

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

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

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 studio),但现在我不知道该怎么用它。

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

更新:

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

We have been debugging a strange case for some days now, and have somewhat isolated the bug, but it still doesn't make any sense. Perhaps anyone here can give me a clue about what is going on.

The problem is an access violation that occur in a part of the code.

Basically we have something like this:

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! 
}

While in the debugger it actually looks like it is destructing the UnreachableClass, and when I insert the DummyDestruct object this does not get destroyed before the strange destructor are called. So it is not seem like the destruction of the LargeObject is going awry.

All this is in the middle of production code, and it is very hard to isolate it to a small example.

My question is, does anyone have a clue about what is causing this, and what is happening? I have a quite full featured debugger available (Embarcadero RAD studio), but now I am not sure what to do with it.

Can anyone give me some advise on how to proceed?

Update:

I placed a DummyDestruct object beneath the throw clause, and placed a breakpoint in the destructor. The destructor for this object is entered (and its only us is in this piece of code).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

私野 2024-08-29 23:35:31

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

With the information you have provided, and if everything is as you state, the only possible answer is a bug in the compiler/optimizer. Just add the extra scope with a comment (This is, again, if everything is exactly as you have stated).

叹沉浮 2024-08-29 23:35:31

有时,由于通过未初始化的指针进行写入、越界数组访问等,会发生类似的情况。引起错误的点可能与它出现的位置相去甚远。但是,根据您描述的症状,它似乎局限于此功能。 LargeObject 的复制构造函数是否行为不当?正在使用 ref 吗?也许 somePtr 没有指向有效的 SomeObjectSingleton() 是否返回指向有效对象的指针?
编译器错误也是有可能的,尤其是在打开积极优化的情况下。我会尝试在不进行优化的情况下重新创建该错误。

Stuff like this sometimes happens due to writing through uninitialized pointers, out of bounds array access, etc. The point at which the error is caused may be quite removed from the place where it manifests. However, based on the symptoms you describe it seems to be localized in this function. Could the copy constructor of LargeObject be misbehaving? Is ref being used? Perhaps somePtr isn't pointing to a valid SomeObject. Is Singleton() returning a pointer to a valid object?
Compiler error is also a possibility, especially with aggressive optimization turned on. I would try to recreate the bug with no optimizations.

放低过去 2024-08-29 23:35:31

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

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

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

Time to practice my telepathic debugging skills:

My best guess is your application has a stack corruption bug. This can write junk over the call stack, which means the debugger is incorrectly reporting the function when you break, and it's not really in the destructor. Either that or you are incorrectly interpreting the debugger's information and the object really is being destructed correctly, but you don't know why!

If stack corruption is the case you're going to have a really tough time working out what the root cause is. This is why it's important to implement tonnes of diagnostics (eg. asserts) throughout your program so you can catch the stack corruption when it happens, rather than getting stuck on its weird side effects.

囚我心虐我身 2024-08-29 23:35:31

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

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

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

This might be a real long shot but I'm going to put it out there anyway...

You say you use borland - what version? And you say you see the error in a string - STL? Do you include winsock2 at all in your project?

The reason I ask is that I had a problem when using borland 6 (2002) and winsock - the header seemed to mess up the structure packing and meant different translation units had a different idea of the memory layout of std::string, depending on what headers were included by the translation unit, with predictably disastrous results.

夜未央樱花落 2024-08-29 23:35:31

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

Here's another wild guess, since you mentioned strings. I know of at least one implementation where (STL) string copying is done in a lazy manner (i.e., no actual copying of the string contents takes place until a change is made; the "copying" is done by simply having the target string object point to the same buffer as the source). In that particular implementation (GNU) there is a bug whereby excessive copying causes the reference counter (how many objects are using the same actual string memory after supposedly copying it) to roll over to 0, resulting in all sorts of mischief. I haven't encountered this bug myself, but have been told about it by someone who has. (I say this because one would think that the ref counter would be a 32 bit number and the chances of that ever rolling over are pretty slim, to say the least, so I may not be describing the problem properly.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文