Boost interprocess共享内存初始化不删除对象及异常遗留问题咨询
方案1:注册全局终止处理器保证清理执行
C++程序抛出未处理异常时会调用std::terminate,我们可以注册自定义的终止回调,在回调中清理当前进程创建的共享内存:
#include <exception> #include <vector> #include <mutex> #include <string> #include <algorithm> namespace bip = boost::interprocess; // 全局存储当前进程创建的共享内存名称,线程安全 std::mutex g_shm_names_mutex; std::vector<std::string> g_created_shm_names; void custom_terminate() { std::lock_guard<std::mutex> lock(g_shm_names_mutex); for (const auto& name : g_created_shm_names) { bip::shared_memory_object::remove(name.c_str()); } // 调用默认终止逻辑退出 std::abort(); } class SharedMemBase { protected: bip::shared_memory_object shm_; const std::string name_; bip::shared_memory_object createShm(const std::string &name) { try { return bip::shared_memory_object( bip::create_only, name.c_str(), bip::read_write); } catch (const bip::interprocess_exception &e) { std::cerr << "Shared memory object exists with name: " << name << std::endl; throw e; } } public: // 程序启动时调用一次即可注册终止回调 static void initTerminateHandler() { std::set_terminate(custom_terminate); } SharedMemBase(const std::string &name) : name_(name), shm_(createShm(name)) { std::lock_guard<std::mutex> lock(g_shm_names_mutex); g_created_shm_names.push_back(name_); } ~SharedMemBase() { bip::shared_memory_object::remove(name_.c_str()); // 正常析构后从全局列表移除 std::lock_guard<std::mutex> lock(g_shm_names_mutex); auto it = std::find(g_created_shm_names.begin(), g_created_shm_names.end(), name_); if (it != g_created_shm_names.end()) { g_created_shm_names.erase(it); } } };
- 优点:实现简单,无额外跨进程通信开销,可覆盖所有未处理异常场景
- 缺点:如果进程被
SIGKILL等无法捕获的信号强制杀死,仍然会出现共享内存残留
方案2:启动时自动检测清理无主共享内存
针对进程被强制杀死导致的残留问题,可以在创建逻辑中增加残留校验:如果create_only失败,先判断持有现有共享内存的进程是否还存活,无存活持有进程时直接清理残留再重试创建:
bip::shared_memory_object createShm(const std::string &name) { try { auto shm = bip::shared_memory_object(bip::create_only, name.c_str(), bip::read_write); // 共享内存创建成功后,在头部存储当前进程PID用于后续存活检测 // 此处省略映射共享内存写入PID的逻辑 return shm; } catch (const bip::interprocess_exception &e) { // 创建失败,尝试检测是否是无主残留 try { bip::shared_memory_object existing_shm(bip::open_only, name.c_str(), bip::read_write); // 1. 映射共享内存读取创建进程的PID // 2. 调用系统API(如Linux下的kill(pid, 0)、Windows下的OpenProcess)判断PID是否存活 // 3. 若PID不存在,说明是残留文件,删除后重试创建即可 // if (!is_pid_alive(creator_pid)) { // bip::shared_memory_object::remove(name.c_str()); // return bip::shared_memory_object(bip::create_only, name.c_str(), bip::read_write); // } } catch (...) { // 打开失败说明共享内存已经被其他进程删除,直接重试创建 return bip::shared_memory_object(bip::create_only, name.c_str(), bip::read_write); } // 确认有存活进程持有共享内存,抛出异常 std::cerr << "Shared memory object exists with name: " << name << std::endl; throw e; } }
该方案可以覆盖所有残留场景,哪怕之前的进程被强制杀死也能正常清理,是生产环境更推荐的实现方式。
内容的提问来源于stack exchange,提问作者mro47
相关产品推荐
相关产品推荐

