【问题标题】:Possible stack corruption inside try __finally blocktry __finally 块中可能的堆栈损坏
【发布时间】:2013-06-26 08:21:24
【问题描述】:

我正在处理的新模块中存在堆栈损坏问题,该模块是大型遗留项目的一部分。我的代码是使用 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 块中调用 return 是否错误?如果有,为什么?

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

【问题讨论】:

  • 你的catch块在哪里?
  • @duDE - 函数中没有 catch 块。此函数中发生的任何异常都会被其调用者捕获和处理。

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


【解决方案1】:

正如@duDE 指出的那样,您应该使用一对 __try、__finally 而不是混合使用 C++ try 和 Borland 扩展 __终于

【讨论】:

  • 我会看看这是否有效。 Borland 文档中的示例显示了 try/__finally 的用法,并且似乎还暗示 try__try 可以互换使用。但是,文档不正确已经不是第一次了……
  • 使用 __try/__finallytry/__finally 也会出现同样的问题
  • try__finallý 混合通常效果很好。 IIRC,可能包括 BCB5 的 BCB 的早期版本,在 try/__finally 块内的 return 存在问题。出于这个原因,我总是避免这种情况,即使在以后的版本中也是如此。在这种情况下,我建议完全删除 try/__finally 并改用 RAII 包装器。
【解决方案2】:

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

我能够通过放弃 try / finally 来解决我的问题。我很幸运,我只是删除了 finally 块中的类实例,因此我能够使用 std:: 将 try / finally 替换为范围大括号: auto_ptr 字段来删除有问题的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-17
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多