Почему мой новый оператор не называется
Я хотел видеть, что динамически загружаемая библиотека (загруженная с помощью dlopen и т. Д.) Действительно использует свои новые операторы удаления, а не те, которые определены в вызывающей программе. Поэтому я написал следующую библиотеку .cpp
<code>#include <exception> #include <new> #include <cstdlib> #include <cstdio> #include "base.hpp" void* operator new(size_t size) { std::printf("New of library called\n"); void *p=std::malloc(size); if (p == 0) // did malloc succeed? throw std::bad_alloc(); // ANSI/ISO compliant behavior return p; } void operator delete(void* p) { std::printf("Delete of library called\n"); std::free(p); } class Derived : public Base { public: Derived() : Base(10) { } }; extern "C" { Base* create() { return new Derived; } void destroy(Base* p) { delete p; } } </code>
и скомпилировал это с
<code>g++ -g -Wall -fPIC -shared library.cpp -o library.so </code>
или как занятый русский предложил попробовать (но в итоге ничего не изменилось)
<code>g++ -g -Wall -fPIC -shared -Wl,-Bsymbolic library.cpp -o library.so </code>
Класс Base содержит только значение типа int и функцию get_value () для получения этого значения. После этого я написал client.cpp вот так
<code>#include <exception> #include <new> #include <iostream> #include <cstdlib> #include <cstdio> #include <dlfcn.h> #include "base.hpp" void* operator new(size_t size) { std::printf("New of client called\n"); void *p=std::malloc(size); if (p == 0) // did malloc succeed? throw std::bad_alloc(); // ANSI/ISO compliant behavior return p; } void operator delete(void* p) { std::printf("Delete of client called\n"); std::free(p); } typedef Base* create_module_t(); typedef void destroy_module_t(Base *); int main() { void* handle = dlopen("./library.so", RTLD_LAZY); if (handle == NULL) { std::cout << dlerror() << std::endl; return 1; } create_module_t* create_module = NULL; void* func = dlsym(handle, "create"); if (func == NULL) { std::cout << dlerror() << std::endl; return 1; } else create_module = (create_module_t *)func; destroy_module_t* destroy_module = NULL; func = dlsym(handle, "destroy"); if (func == NULL) { std::cout << dlerror() << std::endl; return 1; } else destroy_module = (destroy_module_t *)func; Base* a = create_module(); std::cout << "Value: " << a->get_value() << std::endl; destroy_module(a); return 0; } </code>
и скомпилировал это с
<code>g++ -Wall -g -o client -ldl client.cpp </code>
При выполнении клиента я получаю только «Новый клиент под названием» и "Удалить клиента с именем". Даже если я использую переключатель компилятора -Bsymbolic для библиотеки, как предложил Employed Russian.
Теперь: что пошло не так? Я думал, что разделяемые библиотеки используют свои собственные новые / удаления, и поэтому вы должны предоставить рядом с фабрикой создать деструктор уничтожить в коде библиотеки.
Дополнительный вопрос: зачем мне функция destroy (Base * p)? Если бы эта функция вызывала только оператор удаления клиента, я мог бы также сделать это сам, т.е. вместо destroy_module (a) рядом с последней строкой.
Ответ, который я нашел: Библиотека также может предоставить новую пару / оператор удаления. Так что, если я сначала использую новую библиотеку, а затем удаляю клиента, я, вероятно, попаду в ловушку. К сожалению, до сих пор я никогда не видел свою библиотеку, использующую ее новую или удаленную ... Так что на оригинальный вопрос до сих пор нет ответа.
Дополнение: я имею в виду только платформу Linux.
Изменить: Важные части находятся в комментариях к Ответу занятого русского языка. Итак, я даю основную подсказку в двух словах: если так назвать gcc
<code>g++ -Wall -g -fPIC -shared library.cpp -o library.so -Wl,-Bsymbolic </code>
библиотека будет использовать собственные операторы new / delete. В противном случае результаты
<code>g++ -Wall -g -fPIC -shared library.cpp -o library.so </code>
в библиотеке, которая использует операторы new / delete вызывающей программы. Спасибо занятым русским!