2016-10-09 3 views
2

Boost.ASIO를 사용하는 공유 라이브러리가로드 될 때 응용 프로그램에서 Boost.Log를 사용하면 충돌이 발생하거나 중단됩니다. 모든 통찰력은 높이 평가 될 것이다. 완전한 cmake-buildable 예제는 아래와 같습니다.Boost.Log 및 Boost.ASIO를 사용하면 충돌이 발생합니다.

main.cpp의 전역 로거 개체 선언이 주석 처리되지 않은 경우 프로그램에서 seg-fault를 즉시 발생 시키거나 resolve() 호출이 아무 작업도 수행하지 않습니다. 왼쪽으로 주석 처리하면 프로그램이 작동합니다.

내가 부스트 1.55, g를 사용하고 있습니다 ++ (우분투 4.8.4-2ubuntu1 ~ 14.04.3) 4.8.4

CMakeLists.txt

cmake_minimum_required (VERSION 2.8) 
project (boosttest) 
add_definitions(-fPIC -pthread -std=c++11) 
find_package(Boost 1.55.0 REQUIRED) 
add_definitions(-DBOOST_LOG_DYN_LINK) 
include_directories(${Boost_INCLUDE_DIRS}) 

# Build the shared lib. 
add_library(testlib SHARED 
    Lib 
) 

target_link_libraries(testlib 
    pthread 
) 

# Build the test app. 
add_executable(testapp 
    main 
) 

target_link_libraries(testapp 
    dl 
    pthread 
    boost_system 
    boost_log 
) 

하여 Main.cpp

#include <iostream> 
#include <memory> 
#include <dlfcn.h> 
#include <boost/log/core.hpp> 
#include <boost/log/sources/channel_logger.hpp> 

#include "Lib.h" 

using LoggerType = boost::log::sources::channel_logger_mt<>; 
//LoggerType gLogger; // If this is uncommented then probably a crash. 


std::unique_ptr<Lib> LoadLib(const std::string& libName) { 
    typedef Lib* (*LibConstructor)(); 

    union FunctionLookup { 
     LibConstructor entry; 
     void* voidPtr; 
    }; 

    void* handle = ::dlopen(libName.c_str(), RTLD_LAZY); 
    if (!handle) { 
     throw std::runtime_error(::dlerror()); 
    } 

    FunctionLookup lookup; 

    lookup.voidPtr = ::dlsym(handle, "create"); 
    if (!lookup.voidPtr) { 
     throw std::runtime_error(::dlerror()); 
    } 

    return std::unique_ptr<Lib>(lookup.entry()); 
} 


int main(int argc, char* argv[]) { 
    try { 
     std::unique_ptr<Lib> lib = LoadLib("./libtestlib.so"); 
     std::cout << "successfully loaded lib\n"; 
     lib->resolve("www.google.com"); 
    } 
    catch (const std::exception& e) { 
     std::cerr << "*** " << e.what() << "\n"; 
    } 

    std::cout << "Exiting" << std::endl; 
    return 0; 
} 

Lib.h

#pragma once 
#include <boost/asio.hpp> 

using boost::asio::ip::tcp; 

class Lib 
{ 
public: 
    Lib(); 
    virtual ~Lib() {} 
    virtual void resolve(const std::string& host); 

private: 
    void onResolve(const boost::system::error_code&, tcp::resolver::iterator); 

    boost::asio::io_service m_ioService; 
    tcp::resolver m_resolver; 
}; 

Lib.cpp

+0

당신이 대답을 본 적이 : http://stackoverflow.com/questions/35225234/linking-libboost-log-so-makes-boostasioio-servicerun-exit-immediately/ 35241050 # 35241050? –

+0

@AndreySemashev 방금 읽었습니다. 위의 코드에서 볼 수 있듯이 두 바이너리는 동일한 소스 트리에서 빌드되므로 버전 문제는 없습니다. 공유 lib는 ASIO의 헤더 전용 버전을 사용합니다. 이 문제는 동일한 lib를 사용하는 두 개의 바이너리가 원인이라고 말하고 있습니까? – James

+0

호환성 문제는 다른 버전의 라이브러리 (예 : 다른 Boost 버전)로 인해 발생했을뿐만 아니라 * 동일한 * 라이브러리의 다른 구성을 사용하기 때문에 나타날 수 있습니다. 언급 된 대답에서 나는 Boost.ASIO가 호환되지 않는 스위치를 가지고 있으며 그가 Boost.ASIO를 Boost.Log와 그의 코드 모두에서 동일하게 구성된 Boost.ASIO를 사용하는지 확인해야한다고 말했다. –

답변

0

그래서 나는 Boost.Log 라이브러리를 동적으로 링크하지 않음으로써이 문제를 해결할 수있었습니다.

새로운 CMakeLists.txt

cmake_minimum_required (VERSION 2.8) 
project (boosttest) 
add_definitions(-fPIC -pthread -std=c++11) 
find_package(Boost 1.55.0 REQUIRED) 
include_directories(${Boost_INCLUDE_DIRS}) 

# Build the shared lib. 
add_library(testlib SHARED 
    Lib 
) 

target_link_libraries(testlib 
    pthread 
) 

# Build the test app. 
add_executable(testapp 
    main 
) 

target_link_libraries(testapp 
    dl 
    pthread 
    boost_system 
    boost_log.a 
    boost_thread 
)