2017-09-04 26 views
1

我學習C++和正在​​與裝載在Linux(。所以)一個共享庫試驗。負載在C共享庫++使段錯誤

我得到一個分段錯誤,當我運行下面的代碼。

當我嘗試使用Valgrind的運行控制檯應用程序,我得到如下:

valgrind ./TestLoadSo --leak-check=full -v 
==26828== Memcheck, a memory error detector 
==26828== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==26828== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info 
==26828== Command: ./TestLoadSo --leak-check=full -v 
==26828== 
!!!Hello World!!! 
==26828== Jump to the invalid address stated on the next line 
==26828== at 0x0: ??? 
==26828== by 0x53E63F0: (below main) (libc-start.c:291) 
==26828== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==26828== 
==26828== 
==26828== Process terminating with default action of signal 11 (SIGSEGV) 
==26828== Bad permissions for mapped region at address 0x0 
==26828== at 0x0: ??? 
==26828== by 0x53E63F0: (below main) (libc-start.c:291) 
==26828== 
==26828== HEAP SUMMARY: 
==26828==  in use at exit: 3,126 bytes in 9 blocks 
==26828== total heap usage: 13 allocs, 4 frees, 76,998 bytes allocated 
==26828== 
==26828== LEAK SUMMARY: 
==26828== definitely lost: 0 bytes in 0 blocks 
==26828== indirectly lost: 0 bytes in 0 blocks 
==26828==  possibly lost: 0 bytes in 0 blocks 
==26828== still reachable: 3,126 bytes in 9 blocks 
==26828==   suppressed: 0 bytes in 0 blocks 
==26828== Rerun with --leak-check=full to see details of leaked memory 
==26828== 
==26828== For counts of detected and suppressed errors, rerun with: -v 
==26828== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 
[1] 26828 segmentation fault (core dumped) valgrind ./TestLoadSo --leak-check=full -v 

C++主類

extern "C" typedef char* (*helloWorld_t)(); 

int main() { 

    void* handle = dlopen("./libMyLib.dll.so", RTLD_LAZY); 

    if (!handle) { 
    cerr << "Cannot open library: " << dlerror() << '\n'; 
    return 1; 
    } 
    helloWorld_t hello = (helloWorld_t)dlsym(handle, "helloWorld"); 
    const char * tmp = hello(); 
    printf("\n%s",tmp); 

    return 0; 
} 

的外部函數是:

extern "C++" char* helloWorld() { 
    char str[25]; 
    strcpy(str, "HelloWorld"); 
} 

如果我使用extern "C"我得到一個彙編錯誤:

error: conflicting declaration of ‘char* helloWorld()’ with ‘C’ linkage 
extern "C" char* helloWorld() { 

它真的不清楚我在哪裏出錯。

+0

'helloWorld'函數的實現是什麼?還可以使用-O0編譯您的程序以從valgrind獲得更好的信息。 – Serge

+1

'跳轉到下一行指出的無效地址'.so中似乎沒有* helloWorld *符號。你不應該使用'extern「C」'而不是'extern「C++」'? – freakish

+2

您的外部helloWorld也不會返回任何內容。如果你實際上有'return str',那麼這將是一個問題 - 你不應該返回指向棧變量的指針 – lxop

回答

2

許多問題在這裏:

extern "C++" char* helloWorld() { 
    char str[25]; 
    strcpy(str, "HelloWorld"); 
} 

應該使用"C"聯動。它應該返回一些東西。它將字符串複製到局部變量,所以當它返回時值會丟失。所以可能

extern "C" char* helloWorld() { 
    static char str[25]; // will keep its value accross calls, not thread safe 
    return strcpy(str, "HelloWorld"); // return pointer to start of str 
} 

請注意,多個調用都返回相同的靜態緩衝區。如果你需要拷貝,你需要讓調用者提供一個緩衝區,或者返回緩衝區分配爲malloc

+0

謝謝,這有幫助。 – Magick

5

函數不能同時具有C和C++聯動,和一個函數指針類型必須其目標函數的聯動匹配。

您不能dlsymextern "C++"功能由它的樸實無華的名字。你必須在這兩種情況下(推薦),要麼使用extern "C",或使用extern "C++"貫穿並與你的函數的重整名稱替換字符串中dlsym(handle, "helloWorld")推薦)。

總是檢查dlsym的結果,並在返回空指針時報告錯誤(使用dlerror(),就像您爲dlopen所做的那樣)。

不要使用字符數組或指針表示字符串。字符串有一個類型,稱爲std::string

最後但並非最不重要的是,總是用-Wall -Werror進行編譯,因此非實際返回值的非void函數會被捕獲。