如果引入了try-catch,则会出现C ++ Segmentation错误

时间:2016-07-16 09:20:18

标签: c++ boost try-catch

我使用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. 如何安全地检查是否存在所需的段并生成错误消息?
  3. 修改

    我已将块更改为:

    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已经填充了正确的指针,为什么会这么重要?

1 个答案:

答案 0 :(得分:1)

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

managed_shared_memory segment;

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

如果这不是``main`函数,那么让异常转义给调用者(没有尝试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 ++对象。这些对象可以是匿名的,也可以将名称与它们关联起来。

  •   
  • 搜索命名对象的功能。

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

  •   
  • 原子结构和破坏,如果在两个进程之间共享该段,则无法创建两个对象
      与同名相关联,简化了同步。

  •