【问题标题】:thread member function and mex file crash with std::bad_allocstd::bad_alloc 导致线程成员函数和 mex 文件崩溃
【发布时间】:2014-12-21 03:39:38
【问题描述】:

我有一个做一些计算的类(多线程),我用 Matlab 的 mex 文件(在 Linux 中,用 gcc 4.9 编译)包装它,也就是说,mex 有一个变量,它是那个类的一个实例.为了监控计算,该类有两个变量:_did_fit_finish(bool),所以我知道在计算结束时停止监控,_info_str由另一个成员函数更新。监控功能是这样的(g_info_print_interval 是一个全局常量):

template <typename T_Float>
void GmmFit<T_Float>::print_timing(void) {
    std::this_thread::sleep_for(std::chrono::milliseconds(200)); // let the gmm-fit start running
    while ( !_did_fit_finish ) {
        std::cout << _info_str.append("\n");
        std::this_thread::sleep_for(std::chrono::seconds(g_info_print_interval));
    }
}

问题是在退出时,mex 文件导致 matlab 崩溃并显示以下消息:

在抛出 'std::bad_alloc' 的实例后调用终止

崩溃发生在 mex 出口,所以我无法在 mex 代码中尝试捕获它。 一个问题是,除了失败的new 运算符之外,何时引发此类异常?我的代码不会尝试分配大量内存(至少在所描述的用例中不会)

到目前为止我所知道的:

  1. 它只发生在“发布”模式下,也就是说,如果我用mex -g 编译它运行正常。所以我不能用 gdb 调试。
  2. 它发生在特定用例中:mex 函数的特定输入,并从使用 mex 文件的 matlab 脚本中的特定点调用 mex - 这真的很奇怪,因为如果我只调用 mex 而不使用脚本(当然还有完全相同的输入),它不会崩溃。
    1. 如果我禁用监控(下面的MEX_GMM_VERBOSE),它不会崩溃。

这是mex文件中的相关代码块:

 GmmFit<T_Float> gmmFit;
 std::thread readTiming;
 try {
     gmmFit.init(inMat.dimX, inMat.dimY, cfg, initType);
     #ifdef MEX_GMM_VERBOSE
     printf("number of available threads (as returned from std::thread::hardware_concurrency()): %d\n", gmmFit.num_available_threads);
     std::thread readTiming = std::thread(&GmmFit<T_Float>::print_timing, &gmmFit);
     #endif
     model = gmmFit.fit(inMat, initGuess);
     #ifdef MEX_GMM_VERBOSE
     readTiming.detach();
     #endif
  }
catch (...) {
    readTiming.detach();
    mexErrMsgTxt("Unknown exception caught");
}

这是来自 matlab 崩溃消息的堆栈:

Stack Trace (from fault):
[  0] 0x00002aaaad1d4925                                   /lib64/libc.so.6+00207141 gsignal+00000053
[  1] 0x00002aaaad1d6105                                   /lib64/libc.so.6+00213253 abort+00000373
[  2] 0x00002aab417c7be5 /u/itamark/speech-magneton/research/utils/gmmFit/src/mex/mexGmmFit.mexa64+00457701
[  3] 0x00002aab41780f26 /u/itamark/speech-magneton/research/utils/gmmFit/src/mex/mexGmmFit.mexa64+00167718
[  4] 0x00002aab41780f71 /u/itamark/speech-magneton/research/utils/gmmFit/src/mex/mexGmmFit.mexa64+00167793
[  5] 0x00002aab417b9900 /u/itamark/speech-magneton/research/utils/gmmFit/src/mex/mexGmmFit.mexa64+00399616
[  6] 0x00002aaaacf8c9d1                             /lib64/libpthread.so.0+00031185
[  7] 0x00002aaaad28ab6d                                   /lib64/libc.so.6+00953197 clone+00000109

【问题讨论】:

    标签: c++ multithreading matlab c++11 mex


    【解决方案1】:

    您能解释一下为什么要使线程分离而不是连接吗?
    如果没有定义MEX_GMM_VERBOSE,线程根本就没有创建,因此,问题在于线程可运行。
    mex 退出后,相关对象被销毁,但创建的计时线程可能仍在运行,并尝试访问/写入被销毁的对象(_info_str_did_fit_finish)。
    而且,由于像_info_str_did_fit_finish 这样的引用变量也会被其他线程更新,因此它们应该被锁保护。
    因此,我建议你将定时线程加入,并用锁保护_info_str_did_fit_finish

    【讨论】:

    • 原因是,如果采样周期是例如 30 秒,我不想在计算结束后(在最坏的情况下)退出之前等待这额外的 30 秒。
    • 关于锁,改变变量不是有意的——这些变量只能由主线程更新。我会解决的。
    • 好的,似乎使用join 可以避免崩溃(谢谢!) - 但是必须有一个解决方案来解决分离可以访问可能被破坏的资源的线程的用例 - 我是确定这是一个常见的情况,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多