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的操作:
- 在父进程中创建共享的
interprocess_mutex,存储到共享内存里 - 子进程从共享内存中找到这个全局锁,再进行加锁操作
修改后的代码示例
... 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
相关产品推荐
相关产品推荐

