मैंने 2 साझा किए गए libs को --static-libstdc++ सक्षम के साथ संकलित किया।

2 साझा किए गए कामों में एक ही फ़ंक्शन f है, जो सिर्फ एक स्ट्रिंग और एक पूर्णांक को stdout में आउटपुट करता है।

मुख्य कार्यक्रम dlopen का उपयोग करके 2 साझा किए गए कामों को लोड करेगा, और dlsym का उपयोग करके इसमें f को कॉल करेगा।

हालाँकि, दूसरा लोड किया गया साझा लिब पूर्णांक को आउटपुट करने में विफल रहा और C++ स्ट्रीम cout bad & fail बन गया।

जोड़ें: चर्चा के बाद, मुझे पता है कि यह सामान्य है... हालांकि, मैं अपने प्रश्न को इसमें बदलना चाहता हूं: libstdc++ के किस कार्यान्वयन के कारण यह समस्या हुई? क्या कोई साझा वैश्विक स्थिति है? मुझे लगता है कि अगर कोई साझा वैश्विक स्थिति नहीं है, तो यह कोई समस्या नहीं होनी चाहिए। मैंने विंडोज़ में इसी तरह का प्रोग्राम VCRuntime से स्थिर लिंकिंग और लोड लाइब्रेरी का उपयोग करके लिखा था, और यह सामान्य रूप से काम करता है। तो क्यों 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.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

दूसरे भाग पर ध्यान दें, hi और fail & bad के 1 बनने के बाद कोई 1 नहीं है।

result

आप यहां कोड चेकआउट कर सकते हैं: https://github.com/xuhongxu96/dlopen-iostream-issue

2
Hongxu Xu 31 अगस्त 2020, 10:37

1 उत्तर

सबसे बढ़िया उत्तर

अंत में मुझे लिनक्स (जीएनयू एक्सटेंशन) में इस मुद्दे को हल करने का एक तरीका मिला।

dlmopen का उपयोग करें जो बेहतर अलगाव बीटीडब्ल्यू ऑब्जेक्ट प्रदान करता है।

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

सभी टिप्पणीकारों के लिए बहुत बहुत धन्यवाद!

संघर्ष वाले राज्यों के बारे में विवरण समझाने के लिए अभी भी स्वागत है।

0
Hongxu Xu 31 अगस्त 2020, 18:54