You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

boost::interprocess共享内存字符串向量代码触发段错误原因排查

多子进程向Boost共享vector追加字符串时的段错误/冻结问题

编写了一段多子进程向共享vector追加字符串的最小复现代码,程序有时运行正常,但有时在所有子进程结束后会出现冻结或段错误,且段错误似乎发生在父进程访问共享vector时。恳请有Boost使用经验的开发者帮忙调试。

复现代码

...
namespace bip = boost::interprocess;
typedef bip::managed_shared_memory msm;

bip::shared_memory_object::remove("shmem_streak");
bip::managed_shared_memory shm(bip::open_or_create, "shmem_streak", 10000000);
bip::allocator<char, msm::segment_manager> chr_altr(shm.get_segment_manager());
typedef bip::basic_string<char, char_traits<char>, decltype(chr_altr)> str;
bip::allocator<str, msm::segment_manager> str_altr(shm.get_segment_manager());
typedef vector<str, decltype(str_altr)> vec;
shm.construct<vector<str, decltype(str_altr)>>("res_vec")(str_altr);

for (int i = 0, pid; i < num_procs; i++)
{
    if ((pid = fork()) == 0)
    {
        bip::interprocess_mutex mutex;
        bip::scoped_lock<bip::interprocess_mutex> lock(mutex);
        auto child_res_vec = shm.find<vec>("res_vec").first;
        cout << " pushing " << i << " lock: " << endl; //<< lock << endl;
        str tmp_str(chr_altr);
        tmp_str = to_string(i).c_str();
        child_res_vec->push_back(tmp_str);

        exit(0);
    }
    else
        cout << "pid: " << pid << " created" << endl;
}
while (wait(NULL) > 0)
    ;
auto child_res_vec = shm.find<vec>("res_vec").first;
cout << "test res pq: " << endl;
for (auto elem : *child_res_vec)
    cout << elem << endl;
    cout << child_res_vec->back() << endl;
...

错误输出

pid: 91625 created
pid: 91626 created
pid: 91627 created
pid: 91628 created
pushing 1 lock: 
pushing 0 lock: 
pushing 2 lock: 
pushing 3 lock: 
pid: 91629 created
pid: 91630 created
pushing 4 lock: 
pid: 91631 created
pushing 5 lock: 
pid: 91632 created
pushing 6 lock: 
pid: 91633 created
pushing 7 lock: 
pid: 91634 created
pushing 8 lock: 
pid: 91635 created
pushing 9 lock: 
pushing 10 lock: 
pid: 91636 created
pushing 11 lock: 
test res pq: 
zsh: segmentation fault  python app.py

正确输出

pid: 91819 created
pushing 0 lock: 
pid: 91820 created
pushing 1 lock: 
pid: 91821 created
pushing 2 lock: 
pid: 91822 created
pushing 3 lock: 
pid: 91823 created
pushing 4 lock: 
pid: 91824 created
pushing 5 lock: 
pushing 6 lock: 
pid: 91825 created
pid: 91826 created
pushing 7 lock: 
pid: 91827 created
pushing 8 lock: 
pid: 91828 created
pushing 9 lock: 
pushing 10 lock: 
pid: 91829 created
pid: 91830 created
pushing 11 lock: 
test res pq: 
0
1
2
3
4
5
6
7
8
9
10
11

问题分析与修复

核心问题

代码中每个子进程都创建了自己的局部interprocess_mutex,这意味着各个子进程的锁完全独立,根本无法实现跨进程的同步。多个子进程同时对共享vector执行push_back操作,会触发数据竞争,破坏vector的内部结构(比如扩容时的内存操作、size/capacity等成员变量的并发修改),最终导致父进程访问时出现段错误或冻结。

修复方案

必须将互斥量也放到共享内存中,让所有子进程使用同一个锁来保护对共享vector的操作:

  1. 在父进程中创建共享的interprocess_mutex,存储到共享内存里
  2. 子进程从共享内存中找到这个全局锁,再进行加锁操作

修改后的代码示例

...
namespace bip = boost::interprocess;
typedef bip::managed_shared_memory msm;

bip::shared_memory_object::remove("shmem_streak");
bip::managed_shared_memory shm(bip::open_or_create, "shmem_streak", 10000000);
bip::allocator<char, msm::segment_manager> chr_altr(shm.get_segment_manager());
typedef bip::basic_string<char, char_traits<char>, decltype(chr_altr)> str;
bip::allocator<str, msm::segment_manager> str_altr(shm.get_segment_manager());
typedef vector<str, decltype(str_altr)> vec;

// 在共享内存中创建全局互斥量
shm.construct<bip::interprocess_mutex>("vec_mutex")();
// 创建共享vector
shm.construct<vector<str, decltype(str_altr)>>("res_vec")(str_altr);

for (int i = 0, pid; i < num_procs; i++)
{
    if ((pid = fork()) == 0)
    {
        // 从共享内存中获取全局锁
        auto mutex = shm.find<bip::interprocess_mutex>("vec_mutex").first;
        bip::scoped_lock<bip::interprocess_mutex> lock(*mutex);
        
        auto child_res_vec = shm.find<vec>("res_vec").first;
        cout << " pushing " << i << " lock: " << endl;
        str tmp_str(chr_altr);
        tmp_str = to_string(i).c_str();
        child_res_vec->push_back(tmp_str);

        exit(0);
    }
    else
        cout << "pid: " << pid << " created" << endl;
}
while (wait(NULL) > 0)
    ;
auto child_res_vec = shm.find<vec>("res_vec").first;
cout << "test res pq: " << endl;
for (auto elem : *child_res_vec)
    cout << elem << endl;
cout << child_res_vec->back() << endl;
...

内容的提问来源于stack exchange,提问作者VD26

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:40:32