2017-09-04 27 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函数会被捕获。