I have next some project:
main.cpp
#include <iostream>
#include <cstddef>
#include <dlfcn.h>
int main()
{
void* handle = dlopen("./shared_libs/libshared.so", RTLD_LAZY);
if (NULL == handle)
{
std::cerr << "Cannot open library: " << dlerror() << '\n';
return -1;
}
typedef int (*foo_t)(const std::size_t);
foo_t foo = reinterpret_cast<foo_t>(dlsym(handle, "foo"));
const char* dlsym_error = dlerror();
if (dlsym_error)
{
std::cerr << "Cannot load symbol 'foo': " << dlsym_error << '\n';
dlclose(handle);
return -2;
}
std::cout << "call foo" << std::endl;
foo(10);
dlclose(handle);
return 0;
}
shared.cpp:
#include <cstddef>
#include <iostream>
extern "C"
{
int foo(const std::size_t size)
{
int b = size / size;
int* a = new int[size];
std::cout << "leaky code here" << std::endl;
}
}
and Makefile:
all:
g++ -fPIC -g -c shared.cpp
g++ -shared -o shared_libs/libshared.so -g shared.o
g++ -L shared_libs/ -g main.cpp -ldl
I use tcmalloc for debug this test program, which load dynamically libshared.so:foo and execute it.run command:
LD_PRELOAD=/usr/local/lib/libtcmalloc.so HEAPCHECK=normal ./a.out
The 1 largest leaks:
Using local file ./a.out.
Leak of 40 bytes in 1 objects allocated from:
# 7fe3460bd9ba 0x00007fe3460bd9ba
# 400b43 main
# 7fe346c33ec5 __libc_start_main
# 400999 _start
# 0 _init
Why I get address 0x00007fe3460bd9ba instead of line in foo function?
please help
P.s. I tried to use gdb with LD_PRELOAD=.../tcmalloc.so, but I get:
"Someone is ptrace()ing us; will turn itself off Turning perftools heap leak checking off"
Try removing dlclose call.
It's known issue that heap checker & profilers can't handle unloaded
shared objects.
Related
For a legacy project I have to compile our code into a dylib with gcc which is then linked into a clang app starting with Intel-based macOS 10.15 (Catalina). I work with Big Sur 11.4 on a Mac Mini 2020 M1.
For testing purposes, I have created a small C++ project with header
foo.h
#pragma once
class Foo
{
public:
Foo();
virtual ~Foo();
void throw_runtime_error(const char* msg);
int bar(int a);
};
and code foo.cpp
#include <iostream>
#include <stdexcept>
#include "foo.h"
using namespace std;
Foo::Foo()
{
cout << "Foo:Foo() called" << endl;
}
Foo::~Foo()
{
cout << "Foo:~Foo() called" << endl;
}
void Foo::throw_runtime_error(const char* msg)
{
cout << "throwing runtime_error " << msg << endl;
throw runtime_error( msg );
}
int Foo::bar(int a)
{
cout << "Foo::bar(" << a << ") called" << endl;
return a + 1;
}
To create the dylib in a build subdir, I use the homebrewn g++ 10.2 with
g++-10 -arch x86_64 -fexceptions -dynamiclib -I../include ../src/foo.cpp -o ../bin/libMyDylib.dylib
For testing, how to be used along with clang 12.2.0 I have created a main.cpp in the bin subdir
#include "../include/foo.h"
#include <iostream>
#include <stdexcept>
int main()
{
Foo foo;
try
{
foo.throw_runtime_error("Hello you ugly little creatures!");
}
catch( const std::runtime_error &r )
{
std::cout << "Caught foo runtime_error, what = " << r.what() << std::endl;
}
catch( const std::exception &x )
{
std::cout << "Caught foo exception, what = " << x.what() << std::endl;
}
catch(...)
{
std::cout << "Caught foo exception, but without what()" << std::endl;
}
return foo.bar(42);
}
Now, if I use gcc-10 to compile main.cpp and link it with libMyDylib.dylib via g++-10 -arch x86_64 -L/Users/macos/bin -lMyDylib main.cpp -o main the exception handler in main.cpp catches the std::runtime_error properly.
If I use clang 12.2 along with g++ -arch x86_64 -L/Users/macos/bin -lMyDylib main.cpp -o main
then the output shows that only the catch (...) handler is triggered.
./main
Foo:Foo() called
throwing runtime_error Hello you ugly little creatures!
Caught foo exception, but without what()
Foo::bar(42) called
Foo:~Foo() called
So, can someone please give me a hint, what I am missing, in order to get 'cross-compiler' exceptions properly handled?
Thnxalot
I try to test loading a c++ dll module in Lua using "require", below is the c++ module file
#include <stdio.h>
#include <iostream>
extern "C" {
#include "lua/lualib.h"
#include "lua/lauxlib.h"
#include "lua/lua.h"
__declspec(dllexport) int luaopen_mylib(lua_State* L);
}
using namespace std;
static int libFunc1(lua_State* L)
{
int n = lua_gettop(L);
printf("in myfunc stack, arg number: %d\n", n);
if (lua_isstring(L, -1))
{
std::cout << lua_tostring(L, -1) << std::endl;
}
else
{
std::cout << "invalid arg" << std::endl;
}
return 1;
}
static const struct luaL_Reg mylib[] = {{"func1", libFunc1}, {NULL, NULL}};
int luaopen_mylib(lua_State* L)
{
cout << "loading my lib" << endl;
luaL_newlib(L, mylib);
return 1;
}
I compiled this cpp file into dll using g++ in msys:
g++ -c -o mylib.o mylib.cpp
g++ -shared -o mylib.dll mylib.o -Llua -llua5.3.0
until now everything work fine, and I got the mylib.dll file too. but when I try to load the module, I got the error msg:
> require("mylib")
error loading module 'mylib' from file '.\mylib.dll':
找不到指定的程序。
stack traceback:
[C]: in ?
[C]: in function 'require'
stdin:1: in main chunk
[C]: in ?
the Chinese characters above mean:
The specified function could not be found.
I think the "specified function" mean the "luaopen_mylib", but the cpp file do have the function:luaopen_mylib, WHAT IS GOING WRONG?
It might be some name mangling problem. Try:
extern "C"
{
int luaopen_mylib(lua_State* L)
{
cout << "loading my lib" << endl;
luaL_newlib(L, mylib);
return 1;
}
}
Why dynamic loaded library do not appear when you give ldd executable name?Is this true?because I could not find when it is given.
It could be because of dynamic loading and dynamic linking.
Please help me out regarding this and let me know if you need any further details.
The output is as follows.
ldd example6
linux-vdso.so.1 => (0x00007ffe63369000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f56a2676000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f56a2372000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f56a1fa9000)
/lib64/ld-linux-x86-64.so.2 (0x00007f56a287a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f56a1ca3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f56a1a8d000)
I could see only libdl.so...but my executable,example6 is dependent on libtriangle.so which is created for some testing.
If you are accessing the shared libraries without dlopen commands, I am able to find .so details in executable because it is static loading and dynamic linking I feel.
Structure of the Program
Here executable,main makes calls to shared library,libtriangle.so. Shared library,triangle.so makes calls to another shared library,man.so.. man.so makes call to pthread apis
Makefile is present at the end
man.so is obtained using livingbeing.hpp,man.cpp and man.cpp uses pthread apis.man.so depends on -lpthread
triangle.so makes the function calls to man.so. triangle.so access shared library,man.so using dlopen,dlsym commands.
Executable,main is dependent on triangle.so. main acccess triangle.so using dlopen,dlsym functions.
ldconfig is also done for the .so files present in /usr/local/lib/MYDIR
Please find the below files.
livingbeing.hpp
#ifndef LIVINGBEING_HPP
#define LIVINGBEING_HPP
#include <iostream>
using namespace std;
class livingbeing {
protected:
double side_length_;
public:
livingbeing()
: side_length_(0) {}
virtual ~livingbeing() {}
void set_length(double side_length) {
side_length_ = side_length;
}
virtual void eat() = 0;
};
typedef livingbeing* get_instance_t();
typedef void destroy_instance_t(livingbeing*);
#endif
man.cpp
#include "livingbeing.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
class man : public livingbeing {
public:
man()
{
cout<<"man constructor\n";
}
~man()
{
cout<<"man destructor\n";
}
virtual void eat() {
cout<<"man eating\n";
pthread_t thread1, thread2;
int iret1;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) NULL);
pthread_join( thread1, NULL);
}
};
void *print_message_function( void *ptr )
{
cout<<"hello thread1 created";
}
extern "C" livingbeing * get_instance()
{
return new man;
}
extern "C" void destroy_instance(livingbeing *lb)
{
delete lb;
}
triangle.cpp
#include "polygon.hpp"
#include "livingbeing.hpp"
#include <cmath>
#include <dlfcn.h>
//#include <iostream>
class triangle : public polygon {
public:
virtual double area() const {
// load the triangle library
void* man = dlopen("/usr/local/lib/ramu/libman.so", RTLD_LAZY);
if (!man) {
cerr << "Cannot load library: " << dlerror() << '\n';
return 1;
}
// reset errors
dlerror();
// load the symbols
get_instance_t* get_instance_man = (get_instance_t*) dlsym(man, "get_instance");
const char* dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
return 1;
}
destroy_instance_t* destroy_instance_man = (destroy_instance_t*) dlsym(man, "destroy_instance");
dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
return 1;
}
// create an instance of the class
livingbeing* living = get_instance_man();
// use the class
living->set_length(7);
cout << "The livingbeing is: ";
living->eat();
cout<<"\n";
// destroy the class
destroy_instance_man(living);
// unload the triangle library
dlclose(man);
return side_length_ * side_length_ * sqrt(3) / 2;
}
};
// the class factories
extern "C" polygon* create() {
return new triangle;
}
extern "C" void destroy(polygon* p) {
delete p;
}
main.cpp
#include "polygon.hpp"
#include <iostream>
#include <dlfcn.h>
int main() {
using std::cout;
using std::cerr;
// load the triangle library
// void* triangle = dlopen("./triangle.so", RTLD_LAZY);
void* triangle = dlopen("/usr/local/lib/rakesh/libtriangle.so", RTLD_LAZY);
if (!triangle) {
cerr << "Cannot load library: " << dlerror() << '\n';
return 1;
}
// reset errors
dlerror();
// load the symbols
create_t* create_triangle = (create_t*) dlsym(triangle, "create");
const char* dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol create: " << dlsym_error << '\n';
return 1;
}
destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy");
dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol destroy: " << dlsym_error << '\n';
return 1;
}
// create an instance of the class
polygon* poly = create_triangle();
// use the class
poly->set_side_length(7);
cout << "The area is: " << poly->area() << '\n';
// destroy the class
destroy_triangle(poly);
// unload the triangle library
dlclose(triangle);
makefile
example6: main.cpp triangle
$(CXX) $(CXXFLAGS) main.cpp -o example6 -L/usr/local/lib/roh -ltriangle -ldl
triangle: man triangle.cpp polygon.hpp
$(CXX) $(CXXFLAGS) -shared -fPIC triangle.cpp -o libtriangle.so
man: man.cpp livingbeing.hpp
$(CXX) $(CXXFLAGS) -shared -fPIC -o man.so man.cpp -lpthread
clean:
rm -f example6 *.so *.o
.PHONY: clean
Executable main is not dependent on libtriangle in the sense of having libtriangle symbols in its import table. ldd is not aware of the libraries loaded at runtime with dlopen because it does not run or anyhow analyze the code. It only looks at symbols table. Note that even though you explicitly link libtriangle when building executable it has no effect. Linker will only really link library if executable has some unresolved symbols that are located in this library but in case of main executable there is none.
I try to test loading a c++ dll module in Lua using "require", below is the c++ module file
#include <stdio.h>
#include <iostream>
extern "C" {
#include "lua/lualib.h"
#include "lua/lauxlib.h"
#include "lua/lua.h"
__declspec(dllexport) int luaopen_mylib(lua_State* L);
}
using namespace std;
static int libFunc1(lua_State* L)
{
int n = lua_gettop(L);
printf("in myfunc stack, arg number: %d\n", n);
if (lua_isstring(L, -1))
{
std::cout << lua_tostring(L, -1) << std::endl;
}
else
{
std::cout << "invalid arg" << std::endl;
}
return 1;
}
static const struct luaL_Reg mylib[] = {{"func1", libFunc1}, {NULL, NULL}};
int luaopen_mylib(lua_State* L)
{
cout << "loading my lib" << endl;
luaL_newlib(L, mylib);
return 1;
}
I compiled this cpp file into dll using g++ in msys:
g++ -c -o mylib.o mylib.cpp
g++ -shared -o mylib.dll mylib.o -Llua -llua5.3.0
until now everything work fine, and I got the mylib.dll file too. but when I try to load the module, I got the error msg:
> require("mylib")
error loading module 'mylib' from file '.\mylib.dll':
找不到指定的程序。
stack traceback:
[C]: in ?
[C]: in function 'require'
stdin:1: in main chunk
[C]: in ?
the Chinese characters above mean:
The specified function could not be found.
I think the "specified function" mean the "luaopen_mylib", but the cpp file do have the function:luaopen_mylib, WHAT IS GOING WRONG?
It might be some name mangling problem. Try:
extern "C"
{
int luaopen_mylib(lua_State* L)
{
cout << "loading my lib" << endl;
luaL_newlib(L, mylib);
return 1;
}
}
Currently I test a shared library vendor provided in linux ,
the following is the simple source :
#include <iostream>
using namespace std;
extern int test1();
extern int test2();
int main()
{
cout << "hello world" << endl ;
return 0 ;
cout << "Test 1" << endl;
test1();
cout << "Test 2" << endl;
test2();
return 0;
}
I have compile and link like :
g++ -g -Wall -fPIC -D_DEBUG -o test -I./include32 src/xxx.cpp src/yyy.cpp src/test.cpp
-L./lib32 -lshare1 -lshared2
I have the following output while run :
hello world
***glibc detected *** ./test: double free or corrution (!prev) 0x00000000077ec30 ***
What I don't get is , since I only do print "hello world" and then return 0 ,
that mean I don't call any function in libshared1.so and libshared2.so ,
why error like glibc detected happen ? does it mean that shared library has
problem to be loaded to memory ? since the main function never call test1() , test2()
which really call functions in libshared1.so and libshared2.so !!
And suggestions , comments are most appreciated !!
Edit :
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
using namespace std;
int main()
{
cout << "hello world 3 " << endl ;
void *handle2;
handle2 = dlopen ("/usr/local/lib/xxx.so", RTLD_LAZY);
if (!handle2) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
cout << "hello world 1 " << endl ;
void *handle3;
handle3 = dlopen ("/usr/local/lib/yyy.so", RTLD_LAZY);
if (!handle3) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
cout << "hello world" << endl ;
}
Compile :
g++ -g -Wall -rdynamic -o test src/test.cpp -ldl
Output :
hello world 3
hello world 1
Segmentation fault (core dumped)
The Vendor really provide damaged shared library ?!