여러 공유 라이브러리에서 호출되고 libstdc ++ 정적 링크가 활성화 된 경우 C ++ 스트림이 잘못됨

쑤 홍수

--static-libstdc ++를 활성화하여 2 개의 공유 라이브러리를 컴파일했습니다.

2 개의 공유 라이브러리는 동일한 함수를 가지며, f문자열과 정수를 stdout에 출력합니다.

주요 프로그램은 사용이 공유 libs와로드 dlopen, 그리고 전화 f는 사용하여 dlsym.

그러나 두 번째로로드 된 공유 라이브러리는 정수 출력에 실패했으며 C ++ 스트림 coutbad & fail.

ADD : 토론 후 이것이 정상이라는 것을 알고 있습니다 ... 그러나 내 질문을 변경하고 싶습니다. libstdc ++ 구현이이 문제를 일으켰습니까? 공유 된 글로벌 상태가 있습니까? 공유 된 글로벌 상태가 없다면 문제가되지 않을 것 같습니다. VCRuntime에 정적 연결하고 LoadLibrary를 사용하여 Windows에서 유사한 프로그램을 작성했으며 정상적으로 작동합니다. 그렇다면 libstdc ++가 이렇게 설계된 이유는 무엇입니까?


다음은 2 개의 공유 라이브러리에 대한 코드입니다. (동일한 코드를 공유합니다.)
그들은 단지 cout문자열과 정수일 것입니다.

// dll.cpp

#include <iostream>

using namespace std;

extern "C" void f()
{
    cout << "hi" << 1 << endl;

    bool is_eof = cout.eof();
    bool is_fail = cout.fail();
    bool is_bad = cout.bad();

    cout.clear();

    cout << endl;
    cout << "eof: " << to_string(is_eof) << endl;
    cout << "fail: " << to_string(is_fail) << endl;
    cout << "bad: " << to_string(is_bad) << endl;
}

이것은 공유 라이브러리를로드하고 해당 f함수를 호출하는 기본 프로그램 입니다.

// main.cpp

#include <iostream>
#include <dlfcn.h>
#include <cassert>

using namespace std;

using fn_t = void(void);

void call_f_in_dll(const char *dll_path)
{
    auto dll = dlopen(dll_path, RTLD_LAZY);
    assert(dll);
    fn_t *fn = (fn_t *)dlsym(dll, "f");
    assert(fn);
    fn();
    dlclose(dll);
}

int main()
{
    call_f_in_dll("./libmydll.so");

    cout << endl;

    call_f_in_dll("./libmydll2.so");

    return 0;
}

다음은 CMakeLists입니다.

# CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project (TestGCC)

add_link_options(-static-libgcc -static-libstdc++)

add_library(mydll SHARED dll.cpp)
add_library(mydll2 SHARED dll.cpp)

add_executable (main main.cpp)
target_link_libraries(main dl)

출력은 다음과 같습니다.

hox@HOX-PC:~/repos/test-gcc/out$ ./main
hi1

eof: 0
fail: 0
bad: 0

hi
eof: 0
fail: 1
bad: 1

두 번째 부분을 주목, 더이없는 1hifail & bad1.

결과

여기에서 코드를 확인할 수 있습니다 : https://github.com/xuhongxu96/dlopen-iostream-issue

쑤 홍수

마지막으로 Linux (GNU 확장)에서 문제를 해결하는 방법을 찾았습니다.

dlmopen더 나은 격리 btw 객체를 제공하는 사용 .

auto dll = dlmopen(LM_ID_NEWLM, dll_path, RTLD_LAZY);

모든 댓글 작성자에게 감사드립니다!

갈등 상태에 대한 자세한 설명을 환영합니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관