cra sh в boost :: interprocess :: shared_memory_object, если используется / MTd - PullRequest
0 голосов
/ 17 января 2020

У меня есть простой проект под Windows. Он состоит из двух DLL и одного EXE. EXE загружает две библиотеки DLL. Каждый из них создаст объект разделяемой памяти в классе, созданном глобализацией std :: unique_ptr. Cra sh происходит во время FreeLibrary, и только если я использую ключ / MTd (многопоточная отладка) вместо / MDd (многопоточная отладочная DLL).

Я собрал буст-библиотеки, используя:

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;
}

1 Ответ

0 голосов
/ 31 января 2020

Я думаю, что решил проблему (возможно, только для меня). Проблема не в переключателе /MTd компилятора. Я думаю, что проблема связана с реализацией синглтона внутри boost::interprocess::shared_memory_object. Моя структура проекта выглядит следующим образом:

Файл EXE загружает DLL (оболочку драйвера), которая может загружать несколько DLL драйверов устройства параллельно. Две из DLL драйверов используют свои собственные shared_memory_object, как описано в do c, и это работает в обоих случаях. Пока я не вызову FreeLibrary для DLL драйверов. В этом случае всегда второй сбой FreeLibrary (но не с /MDd Я не понял этого факта секунд, извините).

Я решил проблему, создав boost::interprocess::shared_memory_object внутри DLL-оболочки оболочки драйвера. Я просто создаю экземпляр такого объекта и в следующей строке удаляю его. Если я сделаю это, мои библиотеки DLL больше не будут sh.

Надеюсь, это поможет разработчику boost::interprocess.

С уважением, Кристиан

...