Magick
Magick

Reputation: 5132

Load shared lib in c++ causes segmentation fault

I am learning c++, and am experimenting with loading a shared lib on linux (.so).

I get a segmentation fault when I run the below code.

When I try to run the console app using valgrind, I get the following:

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++ Main class

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;
}

The extern function is:

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

If I use extern "C" I get a compilation error:

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

Its really not clear to me where I am going wrong.

Upvotes: 1

Views: 1086

Answers (2)

n. m. could be an AI
n. m. could be an AI

Reputation: 120079

A function cannot have both C and C++ linkage, and a function pointer type must match its target function's linkage.

You cannot dlsym an extern "C++" function by its unadorned name. You have to either use extern "C" in both cases (recommended), or use extern "C++" throughout and replace the string in dlsym(handle, "helloWorld") with the mangled name of your function (not recommended).

Always check the result of dlsym and report an error if it returns a null pointer (use dlerror() like you've done for dlopen).

Don't use character arrays or pointers to represent strings. There is a type for string, called std::string.

Last but not least, always compile with -Wall -Werror so things like a non-void function that doesn't actually return a value will be caught.

Upvotes: 5

hyde
hyde

Reputation: 62908

Many problems here:

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

It should use "C" linkage. And it should return something. And it copies the string to local variable, so value gets lost when it returns. So probably

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
}

Note that multiple calls all return same static buffer. If you need copies, you need to let caller provide a buffer, or return buffer allocated with malloc.

Upvotes: 2

Related Questions