try __finally块中可能存在堆栈损坏

时间:2013-06-28 14:15:32

标签: c++ try-finally c++builder-5

我正在处理新模块中的堆栈损坏问题,这是一个大型遗留项目的一部分。我的代码是使用Borland C ++ Builder 5.0用C ++编写的。

我已将问题跟踪到以下功能:

// Note: Class TMarshalServerClientThread has the following objects defined
// CRITICAL_SECTION                 FCriticalSection;
// std::vector<TMarshalTagInfo*>    FTagChangeQueue;

void __fastcall TMarshalServerClientThread::SendChangeNotifications()
{
   EnterCriticalSection(FCriticalSection);

   try {
      if (FTagChangeQueue.size() == 0) {         
         return;
      }

      // Process items in change queue

      FTagChangeQueue.clear();

   } __finally {
      LeaveCriticalSection(FCriticalSection);
   }
}

在工作线程(从TThread下降)的上下文中调用此函数。当数据变为可用时,另一个线程会使用数据填充更改队列。更改队列受关键部分对象保护。

当代码运行时,我偶尔会在尝试离开临界区时遇到访问冲突。据我所知,有时当输入 __ finally 部分时,堆栈已损坏。堆上的类实例很好,但是指向类的指针(例如“this”指针)似乎无效。

如果我在更改队列为空时删除了要返回的调用,则问题就会消失。此外,处理队列中的项目的代码不是问题的根源,因为我可以将其注释掉,问题仍然存在。

所以我的问题是在C ++ Builder 5中使用 __ finally 时是否存在已知问题?从 try __finally 块中调用返回是不对的?如果是这样,为什么?

请注意,我意识到有不同/更好的方法来做我正在做的事情,我正在重构。但是,我不明白为什么这些代码应该导致堆栈损坏。

2 个答案:

答案 0 :(得分:1)

正如@duDE指出的那样,你应该使用 __ 尝试,_ _最终,而不是混合C ++ 尝试,并且Borland扩展 __最后

答案 1 :(得分:1)

我知道在原始问题发布后很长一段时间,但作为对其他人的警告,我可以保证Jonathan Wiens报告的症状。我用Builder XE4体验过它。它并不经常发生,但似乎Borland / Embarcadero在多线程进程中实现 try / finally 块会偶尔破坏堆栈。我也在使用关键部分,尽管这可能是巧合。

我可以通过放弃 try / finally 来解决我的问题。我很幸运,我只删除 finally 块中的类实例,因此我能够使用 std ::替换 try / finally 和范围括号auto_ptr 字段,用于删除相关对象。