线程成员函数和mex文件因std::bad_alloc而崩溃

thread member function and mex file crash with std::bad_alloc

本文关键字:bad alloc 崩溃 std 函数 成员 mex 文件 线程      更新时间:2023-10-16

我有一个用于进行一些计算的类(多线程),我用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"实例后调用terminate

崩溃发生在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()): %dn", 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

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