terminate called after throwing an instance of ‘std::regex_error‘解决办法

文章讲述了在CentOS7.9环境下,C++11程序编译正常但运行时遇到regex_error的问题。解决方法是通过安装DeveloperToolset7软件集合,使用devtoolset-7版本的GCC,更新编译环境后解决问题。

CentOS 7.9下的C++ 11程序编译正常,运行时报错:

terminate called after throwing an instance of 'std::regex_error'

what(): regex_error

Aborted

解决办法:

经查询gcc4.9才支持c++的正则表达式,所以我们需要将gcc进行升级。

不需要这样做,因为即使升级后,可能还是会运行出错。

测试有效的解决办法:

安装: Developer Toolset 7

# 1. Install a package with repository for your system:
# On CentOS, install package centos-release-scl available in CentOS repository:
$ sudo yum install centos-release-scl

# On RHEL, enable RHSCL repository for you system:
$ sudo yum-config-manager --enable rhel-server-rhscl-7-rpms

# 2. Install the collection:
$ sudo yum install devtoolset-7

# 3. Start using software collections:
$ scl enable devtoolset-7 bash

对代码重新编译后即可!

<think>我们正在处理两个相关的错误: 1. terminate called after throwing an instance of &#39;terminate called recursively&#39; 2. terminate called recursively 根据之前的讨论,这些错误通常与异常处理和锁的递归使用有关。结合用户提供的引用,我们注意到两个关键点: 引用[1]:显示了一个NVDECException异常,这可能是由于视频解码时的CUDA错误(错误代码716)引起的。 引用[2]:展示了一个异常处理中由于catch语句未正确捕获异常(需要将char*改为const char*)而导致的错误。 但是,用户现在明确要求解决“terminate called recursively”和“terminate called after throwing an instance of &#39;terminate called recursively&#39;”错误。 回顾我们之前的回答,我们主要讨论了由于递归加锁导致的terminate called recursively错误。然而,用户现在可能遇到了更复杂的情况,即异常处理过程中又发生了terminate调用,导致递归终止。 因此,我们应当从两个方面入手: 1. 检查异常处理是否完备(避免未捕获的异常导致std::terminate被调用) 2. 检查锁的使用(避免递归加锁) 特别地,错误信息“terminate called after throwing an instance of &#39;terminate called recursively&#39;”表明: - 程序首先抛出了一个异常(throw),但在异常处理过程中,又发生了导致terminate被调用的情况(例如未捕获的异常),而在terminate的处理过程中又发生了异常,导致递归调用terminate。 这是一个非常严重的情况,通常意味着异常处理机制被破坏。 解决步骤: ### 1. **确保所有异常都被正确捕获** - C++中,如果异常未被捕获,则会调用`std::terminate`。如果在一个异常处理过程中(例如在析构函数或`noexcept`函数中)又抛出了异常,则会导致`std::terminate`被递归调用。 - 检查代码中所有可能抛出异常的地方,确保有适当的`catch`块。 - 特别注意:在析构函数和声明为`noexcept`的函数中,避免抛出异常。 示例:在析构函数中抛出异常是危险的,因为如果析构函数是因为栈展开(处理异常)而调用,那么此时再抛出异常会导致`std::terminate`。 ```cpp class MyClass { public: ~MyClass() noexcept(false) { // 不推荐,析构函数最好不抛出异常 // ... 可能抛出异常的操作 } }; ``` 修复:在析构函数中捕获异常并处理,避免异常传播到析构函数之外。 ```cpp class MyClass { public: ~MyClass() noexcept { try { // ... 可能抛出异常的操作 } catch (...) { // 记录错误,但不要重新抛出 } } }; ``` ### 2. **检查递归加锁问题** 如之前所述,同一线程对非递归锁(如`std::mutex`)进行递归加锁会导致未定义行为(通常是抛出`std::system_error`异常)。如果这个异常没有被捕获,就会导致`std::terminate`被调用。 因此,检查所有锁的使用: - 确保不重复加锁。 - 使用递归锁(`std::recursive_mutex`)如果确实需要递归加锁。 ### 3. **检查异常处理中的异常安全** 在异常处理过程中(catch块内)也可能抛出异常。如果catch块内抛出的异常没有被该catch块内的嵌套try-catch捕获,则会导致未捕获的异常,从而再次调用`std::terminate`。 示例: ```cpp try { // 代码可能抛出异常 } catch (const MyException& e) { // 处理过程中可能抛出新的异常 throw; // 或者某个操作抛出异常 } ``` 修复:在catch块内部使用嵌套的try-catch,确保catch块内不会再抛出未捕获的异常。 ```cpp try { // ... } catch (const MyException& e) { try { // 处理异常,可能会抛出 } catch (...) { // 处理内部异常 } } ``` ### 4. **使用自定义terminate处理函数** 可以设置自定义的terminate处理函数来获取更多信息: ```cpp #include <exception> #include <iostream> void my_terminate() { std::cerr << "Terminate called. Backtrace:" << std::endl; // 这里可以打印堆栈信息(需要平台相关支持) std::abort(); // 必须终止程序 } int main() { std::set_terminate(my_terminate); // ... } ``` 注意:在自定义terminate处理函数中,不能有异常抛出,且必须终止程序。 ### 5. **调试与日志** - 使用GDB调试:运行程序,当terminate被调用时,GDB会中断,此时可以查看堆栈回溯(backtrace)。 - 在关键位置添加日志,特别是锁操作和异常捕获点。 ### 6. **针对引用[1]中视频解码错误的建议** 用户引用[1]中的错误是NVDECException,发生在NvDecoder.cpp中。这个异常被抛出后如果没有被捕获,就会导致terminate。而如果在这个异常的处理过程中又发生了问题(比如析构函数中抛出异常或锁的问题),则会导致递归terminate。 因此,需要确保捕获这个NVDECException,并安全处理。 ```cpp try { // 调用视频解码的代码 } catch (const NVDECException& e) { // 安全地处理解码异常,注意不要在这个块中再抛出异常(除非有嵌套try-catch) std::cerr << "NVDEC Error: " << e.what() << std::endl; // 进行清理,不要重新抛出 } catch (...) { // 捕获其他所有异常 } ``` 总结: 错误“terminate called recursively”通常表示在程序终止过程中又发生了异常,这往往是由于异常处理不当(如在析构函数或terminate处理函数中抛出异常)或递归加锁导致未捕获异常而引起的。解决的关键是: - 确保所有异常都被捕获,特别是在析构函数和异常处理过程中。 - 避免在析构函数中抛出异常。 - 检查锁的使用,避免递归加锁。 - 在异常处理代码中保证异常安全(使用嵌套try-catch)。 由于问题可能涉及多个层次,需要结合日志和调试工具定位具体错误点。 相关问题: 1. 如何在C++中设置自定义终止处理函数? 2. 如何避免在析构函数中抛出异常? 3. 如何在C++中调试未捕获的异常? 4. 如何安全地处理NVDECException等第三方库异常? </think> ### 解决 "terminate called recursively" 和 "terminate called after throwing an instance of &#39;terminate called recursively&#39;" 错误 这两个错误通常表示程序在异常处理过程中发生了**递归终止调用**,本质是异常处理机制被破坏。以下是系统性的解决方案: --- ### 1. **检查未捕获的异常(核心问题)** 当异常未被捕获时,C++ 会调用 `std::terminate()`。若在终止过程中又抛出异常,则触发递归终止[^1]。 **修复步骤**: ```cpp int main() { try { // 所有可能抛异常的代码 videoProcessing(); // 引用[1]中的视频处理函数 } catch (const NVDECException& e) { // 捕获特定异常 std::cerr << "NVDEC Error: " << e.what() << std::endl; } catch (...) { // 捕获所有其他异常 std::cerr << "Unknown exception" << std::endl; } return 0; } ``` > 📌 **关键**:确保所有异常(包括第三方库异常如 `NVDECException`)都被显式捕获[^1][^2]。 --- ### 2. **检查析构函数中的异常** 析构函数中抛出异常会导致递归终止(尤其在栈展开时)。 **修复方法**: ```cpp class ResourceHolder { public: ~ResourceHolder() noexcept { // 声明 noexcept try { cleanup(); // 可能抛异常的操作 } catch (...) { // 仅记录日志,不重新抛出 log("Cleanup failed"); } } }; ``` > ⚠️ 析构函数必须用 `noexcept` 声明,并在内部捕获所有异常。 --- ### 3. **验证锁的递归使用** 同一线程对 `std::mutex` 递归加锁会抛出 `std::system_error`,若未捕获则触发终止[^2]。 **解决方案**: ```diff std::mutex mtx; void threadFunc() { std::unique_lock<std::mutex> lock(mtx); // 加锁 // ... 临界区代码 ... - lock.lock(); // 错误:递归加锁(删除此行) } // 自动解锁 ``` 或改用递归锁: ```cpp std::recursive_mutex rmtx; // 允许同一线程递归加锁 ``` --- ### 4. **检查自定义终止处理函数** 若设置了 `std::set_terminate()`,处理函数**禁止抛出异常**: ```cpp void safeTerminate() noexcept { // 必须声明 noexcept std::cerr << "Terminating" << std::endl; std::abort(); // 直接终止,不抛异常 } int main() { std::set_terminate(safeTerminate); // ... } ``` --- ### 5. **调试与日志追踪** **GDB 诊断**: ```bash gdb ./your_program (gdb) catch throw # 捕获异常抛出点 (gdb) run (gdb) bt full # 查看完整调用栈 ``` **关键日志点**: ```cpp try { std::cout << "Before risky operation\n"; riskyOperation(); // 引用[1]中的视频解码调用 } catch (...) { std::cout << "Exception caught at line:" << __LINE__ << std::endl; } ``` --- ### 错误发生流程图 ```mermaid graph TD A[主线程抛出未捕获异常] --> B[调用 std::terminate] B --> C[执行 terminate_handler] C --> D{handler 内是否抛异常?} D -->|是| E[递归调用 terminate] D -->|否| F[程序终止] E --> G[输出 &#39;terminate called recursively&#39;] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北雨南萍

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值