Я написал пользовательскую библиотеку, реализующую malloc/calloc/realloc/free с использованием стандартных прототипов C, и понял, как скомпилировать ее в файл so. Я хочу протестировать библиотеку, связав с ней стандартное приложение? Что было бы хорошим способом сделать это? Когда у меня есть рабочая библиотека, я предполагаю, что могу просто загрузить ее с помощью LD_PRELOAD, но как мне заставить мои функции сосуществовать, но иметь приоритет над функциями системной библиотеки? Моим функциям нужно сделать вызов malloc, чтобы запустить память, поэтому я не могу просто полностью отказаться от stdlib... Помогите?
Компиляция пользовательского malloc
Ответы (3)
Функции, которые вы пытаетесь заменить, являются стандартными функциями C, а не макросами и не системными вызовами. Поэтому вам нужно просто дать своим функциям одинаковые имена и скомпилировать их в разделяемую библиотеку.
Затем используйте LD_PRELOAD
для предварительной загрузки вашей библиотеки перед запуском двоичного файла. Так как все адреса резолвятся один раз, компоновщик вычислит адреса ваших функций и запомнит их имена и не будет потом искать их в стандартной библиотеке.
Этот подход может не сработать, если ваша программа связана со стандартной средой выполнения статически. Кроме того, это не будет работать в Mac OS X, так как есть другой API для интерполяции.
В Linux, например, для того, чтобы ваши функции сосуществовали (т.е. если вы хотите использовать систему malloc
в собственной реализации malloc
), вы должны открыть стандартную библиотеку вручную с помощью dlopen
, найти там нужные вам функции с помощью dlsym
и позвоните им позже по адресу.
Не записывайте свой malloc()
в терминах malloc()
— пишите его, используя sbrk
, который получает память непосредственно из ОС.
sbrk()
больше не доступен. Например, в моем текущем Mac OS X человек говорит The brk and sbrk functions are historical curiosities left over from earlier days before the advent of virtual memory management.
, и если вы посмотрите полный исходный код функции, это будет еще смешнее: errno = ENOMEM; return((void *)-1);
- person achedeuzot; 20.01.2015
Если у вас есть контроль над исходным кодом, который должен использовать эту библиотеку, вот одна из возможностей. Используйте разные имена функций: вместо malloc, например, назовите ее newCoolMalloc. Этот метод иногда проще и не зависит от специальных опций компоновщика.
Затем в своем коде используйте #define
, чтобы код вызывал нужный набор функций. Вы можете #define malloc сделать что-то другое. Например:
#define malloc newCoolMalloc
#define free newCoolFree
Однако, если вы делаете это, вы должны быть очень осторожны, чтобы включать это постоянно. В противном случае вы рискуете использовать stdlib malloc в одном месте, а затем свой собственный free в другом, что приведет к грязным ошибкам. Один из способов смягчить эту ситуацию — использовать (если возможно) в собственном коде собственные имена для функций распределения и свободных функций. Тогда легче убедиться, что вызывается правильный. Вы можете определить различные пользовательские имена для ваших собственных функций malloc или даже для исходных функций malloc stdlib.
Например, вы можете использовать mallocPlaceHolder в качестве фактического имени в коде:
someThing = mallocPlaceHolder( nbytes );
Тогда ваши определения будут выглядеть примерно так:
#define mallocPlaceHolder myCoolMalloc
Если на самом деле не существует функции вида mallocPlaceHolder (и связанной с ней бесплатной), это позволяет избежать смешивания разных библиотек.