如果使用/ MTd,则会在boost :: interprocess :: shared_memory_object中崩溃

问题描述 投票:0回答:1

我有一个在Windows下运行的简单项目。它由两个DLL和一个EXE组成。EXE加载两个DLL。每个类都将在由std :: unique_ptr全局性实例化的类中创建一个共享内存对象。只有在使用/ MTd开关(多线程调试)而不是/ MDd(多线程调试DLL)的情况下,崩溃才会在FreeLibrary中发生。

我使用以下方法构建了增强库:

b2.exe -a -j %NUMBER_OF_PROCESSORS% --prefix=%BOOST% --libdir=%BOOST%/lib/x86 --reconfigure --build-type=complete --toolset=msvc-14.2 link=static address-model=32 runtime-link=static runtime-link=shared threading=multi define=BOOST_USE_WINDOWS_H define=NOMINMAX install

%BOOST%指向我的BOOST安装文件夹。

我希望有人可以帮助我,基督徒。

示例代码:

APOLLOSHM \ dllmain.cpp

#include <memory>
#include "../shared/SHMBASE.h"

std::unique_ptr<SHM> shm;
BOOL APIENTRY DllMain( HMODULE hModule, 
DWORD ul_reason_for_call, LPVOID )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        shm = std::make_unique<SHM>("a_shm");
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

PHONYXSHM \ dllmain.cpp

#include <memory>
#include "../shared/SHMBASE.h"

std::unique_ptr<SHM> shm;
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        shm = std::make_unique<SHM>("p_shm");
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

shared \ SHMBASE.h

#ifndef SHAREDMEM_H
#define SHAREDMEM_H
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
class SHMBASE
{
    boost::interprocess::shared_memory_object shm;
    boost::interprocess::mapped_region region;
protected:
    void* addr{ nullptr };
public:
    SHMBASE(const char* n)
    {
        try {
            boost::interprocess::shared_memory_object::remove(n);
            shm = boost::interprocess::shared_memory_object(
                  boost::interprocess::open_or_create, 
                  n, boost::interprocess::read_write);
        }
        catch (boost::interprocess::interprocess_exception & ex) {
            throw std::runtime_error(ex.what());
        }
    }
    void create_shm(size_t size)
    {
        shm.truncate(size);
        region = boost::interprocess::mapped_region(shm, 
                 boost::interprocess::read_write);
        addr = region.get_address();
    }
};

struct shared_memory_info
{
    char x[20];
    int y;
};

class SHM : public SHMBASE
{
public:
    SHM(const char* n) :
        SHMBASE(n)
    {
        create_shm(sizeof(shared_memory_info));
        shm = static_cast<shared_memory_info*>(addr);
    }
    shared_memory_info* shm;
};
#endif

SharedMemTest \ SharedMemTest.cpp

#include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <Windows.h>

struct LIBOBJ
{
    HMODULE libhandle{ nullptr };
    LIBOBJ(std::string libname){
        libhandle = LoadLibraryA(libname.c_str());
        if (!libhandle) {
            throw std::runtime_error("Cannot open library");
        }
    }
    ~LIBOBJ() {
        if (libhandle){
            FreeLibrary(libhandle);
        }
    }
};
int main(){
    std::vector<std::string> dlls = {"ApolloSHM.dll", "PhonyxSHM.dll"};
    std::vector<std::unique_ptr<LIBOBJ> > objs;
    try{
        for (auto& n : dlls){
            objs.emplace_back(std::make_unique<LIBOBJ>(n));
        }
        // if freelibrary in reverse order no crash
        // for (auto it = objs.rbegin(); it != objs.rend(); ++it)
        // if in order of loading it crashes, but only with /MTd
        // for (auto it = objs.begin(); it != objs.end(); ++it)
        for (auto it = objs.begin(); it != objs.end(); ++it){
            it->reset();
        }
    }
    catch (std::exception & e){
        std::cout << "Exception: " << e.what() << std::endl;
    }
    return 0;
}
c++ boost shared-memory interprocess
1个回答
0
投票

我想我已经解决了这个问题(也许只是对我来说)。问题不在于编译器的/MTd开关。我认为问题与boost::interprocess::shared_memory_object中的单例实现有关。我的项目结构如下:

一个EXE文件加载一个DLL(驱动程序包装器),该DLL可以并行加载多个设备驱动程序DLL。如文档中所述,两个驱动程序DLL正在使用它们自己的shared_memory_object,并且在两种情况下都可以工作。直到我为驱动程序DLL调用FreeLibrary。在那种情况下,第二个FreeLibrary总是崩溃(但不是/MDd,我不明白这秒钟的事实,对不起)。

我通过在驱动程序包装DLL中创建boost::interprocess::shared_memory_object解决了该问题。我只是实例化了这样一个对象,并在下一行中将其删除。如果执行此操作,我的DLL将不会再崩溃。

希望这对boost::interprocess的开发人员有所帮助。

亲切的问候,基督教

© www.soinside.com 2019 - 2024. All rights reserved.