【问题标题】:C++ Segmentation fault if try-catch is introduced如果引入 try-catch,则 C++ 分段错误
【发布时间】:2026-01-16 16:55:01
【问题描述】:

我正在使用boost::interprocess 运行最简单的进程间通信程序设置:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <cstdlib> //system
#include <iostream>

using namespace std;
using namespace boost::interprocess;
typedef pair<double, int> MyType;

int main(int argc, char *argv[]) {

    if (argc==1) {  //Parent process

        struct shm_remove {
            shm_remove() {shared_memory_object::remove("MySharedMemory");}
            ~shm_remove() {shared_memory_object::remove("MySharedMemory");}
        } remover;

        managed_shared_memory segment(create_only,"MySharedMemory",65536);
        MyType* instance=segment.construct<MyType>("MyType instance")(0.5,2);
        string s(argv[0]);
        s+=" child ";
        if(system(s.c_str())!=0) {
            cout<<"Parent: Child process returned non-zero"<<endl;
            return 1;
        }
        cout<<"Parent: Child process finished successfully"<<endl;
        segment.destroy<MyType>("MyType instance");

    } else { //Child process

        pair<MyType*, managed_shared_memory::size_type> res;
//        try {
            managed_shared_memory segment(open_only, "MySharedMemory");
            res=segment.find<MyType>("MyType instance");
//        } catch (interprocess_exception &e) {
//            cerr<<"Error while opening the segment"<<endl;
//            return 1;
//        }
        cout<<"Child: Segment of length "<<res.second<<" is found at "<<res.first<<endl;
        cout<<"Child: "<<res.first->first<<", "<<res.first->second<<endl;

    }

    return 0;
}

这行得通,我明白了:

Child: Segment of length 1 is found at 0x106a15148
Child: 0.5, 2
Parent: Child process finished successfully

但是,当我取消注释 try-catch 块时,我看到以下内容:

Child: Segment of length 1 is found at 0x10a8fd148
Parent: Child process returned non-zero

如果我将二进制文件分成两部分(生成段和永远休眠的父级和读取段的子级),它在没有 try-cacth 的情况下再次工作,但子级崩溃

Segmentation fault: 11

因此,我有两个问题:

  1. try-catch 的引入是什么原因?它的行为就像块有自己的地址空间一样。但为什么会这样呢?
  2. 如何安全地检查所需段的存在并生成未找到的错误消息?

编辑:

我已将块更改为:

if (1) {
    managed_shared_memory segment(open_only, "MySharedMemory");
    res=segment.find<MyType>("MyType instance");
    cout<<"Child: Segment of length "<<res.second<<" is found at "<<res.first<<endl;
    cout<<"Child: "<<res.first->first<<", "<<res.first->second<<endl;
}

我遇到了同样的错误:

Child: Segment of length 1 is found at 0x108c15148
Child: 0.5, 2
Child: Segment of length 1 is found at 0x108c15148
Parent: Child process returned non-zero

因此,该行为确实是{}造成的,推测是segment被破坏所致。但是,如果 res.first 已经填充了正确的指针,这又有什么关系呢?

【问题讨论】:

  • segment 析构函数是做什么的?看起来它释放了您稍后尝试访问的内容。

标签: c++ boost try-catch


【解决方案1】:

问题似乎是managed_shared_memory的析构函数被调用了,但是在try catch块之后你继续依赖它持有的状态或分配。

managed_shared_memory segment;

回想一下,析构函数总是在作用域的末尾调用(基本上是任何关闭的}),这也适用于 try 块。

如果这不是 ``main` 函数,最好让异常逃逸给调用者(没有 try catch),或者重新抛出它(或另一个异常):

    try {
        managed_shared_memory segment(open_only, "MySharedMemory");
        res=segment.find<MyType>("MyType instance");
        cout<<"Child: Segment of length "<<res.second<<" is found at "<<res.first<<endl;
        cout<<"Child: "<<res.first->first<<", "<<res.first->second<<endl;

    } catch (interprocess_exception &e) {
        cerr<<"Error while opening the segment"<<endl;
        throw;
    }

确实,看看the documentation

托管内存段最重要的服务是:

  • 内存部分的动态分配。

  • 在内存段中构造 C++ 对象。这些对象可以是匿名的,或者我们可以为它们关联一个名称。

  • 搜索命名对象的能力。

  • 许多功能的自定义:内存分配算法、索引类型或字符类型。

  • 原子构造和破坏,因此如果段在两个进程之间共享,则不可能创建两个对象
    关联同名,简化同步。

【讨论】:

  • 那么,segment 的作用不仅仅是提供指向底层数组的正确指针?析构函数是否从进程地址空间中删除地址本身?