Я хотел бы контролировать использование mallocs и освобождаю в приложении при помощи malloc и свободных рычагов.
Вот является документация http://www.gnu.org/s/libc/manual/html_node/Hooks-for-Malloc.html
От страницы в качестве примера Вы видите это my_malloc_hook
кратковременно выключает рычаг malloc (или к предыдущему рычагу в цепочке) прежде, чем повторно вызвать malloc.
Это - проблема при контроле многопоточных приложений (см. конец вопроса для объяснения).
Другие примеры использования рычага malloc, который я нашел в Интернете, имеют ту же проблему.
Существует ли способ переписать эту функцию для работы правильно в многопоточном приложении?
Например, есть ли внутренняя функция libc, которую рычаг malloc может вызвать, который завершает выделение без потребности деактивировать мой рычаг.
Я не могу посмотреть на libc исходный код из-за корпоративной легальной политики, таким образом, ответ может быть очевидным.
Моя спецификация дизайна говорит, что я не могу заменить malloc другим дизайном malloc.
Я могу предположить, что никакие другие рычаги не находятся в игре.
ОБНОВЛЕНИЕ
Так как рычаг malloc временно удален при обслуживании malloc, другой поток может назвать malloc и НЕ получить рычаг.
Было предложено, чтобы malloc имел большую блокировку вокруг этого, которая предотвращает это, но это не документируется, и то, что я эффективно рекурсивно называю malloc, предлагает, чтобы любая блокировка или существовала после рычага или быть весьма умной:
caller ->
malloc ->
malloc-hook (disables hook) ->
malloc -> # possible hazard starts here
malloc_internals
malloc <-
malloc-hook (enables hook) <-
malloc
caller
UPDATED
Вы правы, что не доверяете __malloc_hooks; я взглянул на код, и они - ошеломляюще безумно - небезопасны для потоков.
Вызов унаследованных крючков напрямую, а не восстановление и повторный вход malloc, кажется, отклоняется от документа, который вы цитируете, слишком сильно, чтобы чувствовать себя комфортно, предлагая.
Из http://manpages.sgvulcan.com/malloc_hook.3.php:
Переменные с крючком не являются потокобезопасными, поэтому сейчас они устарели. Вместо этого программисту следует предвосхищать вызовы соответствующих функций, определяя и экспортируя такие функции, как "malloc" и "free".
Надлежащий способ внедрить отладочные функции malloc/realloc/free - предоставить свою собственную библиотеку, которая экспортирует отладочные версии этих функций, а затем отдает предпочтение реальным функциям. Линковка на Си производится в явном порядке, поэтому если две библиотеки предлагают одну и ту же функцию, то используется первая указанная. Вы также можете внедрить свой malloc во время загрузки на unix, используя механизмы LD_PRELOAD.
http://linux.die.net/man/3/efence описывает электрический забор, который подробно описывает оба этих подхода.
Вы можете использовать свой собственный замок, если это необходимо в этих отладочных функциях.
Поскольку все вызовы malloc () будут проходить через ваш крючок, вы можете синхронизировать на семафоре (подождите, пока оно не будет бесплатным, блокировать его, жонглировать крючки и освободить семафор).
[править] IANAL, но ... если вы можете использовать GLIBC в вашем коде, вы можете посмотреть код (поскольку это LGPL, любой, кто его использует , должен быть разрешен иметь копию источника). Поэтому я не уверен, что вы правильно поняли правовую ситуацию или, может быть, вы не можете использовать Glibc в вашей компании.
[edit2] После некоторого мышления, я думаю, что эта часть пути вызова должна быть защищена блокировкой какой-то, какой Glibc создает для вас. В противном случае использование крючков в многопоточенном коде никогда не будет работать надежно, и я уверен, что документы будут упомянуть это. С MALLOC ()
должны быть безопасными потоками, крючки должны быть также.
Если вы все еще обеспокоены, я предлагаю написать небольшую тестовую программу с двумя потоками, которые выделяют и бесплатную память в цикле. Увеличивать счетчик в крючке. После миллиона раундов счетчик должен быть ровно два миллиона. Если это удерживает, то крючок защищен Malloc ()
.
[Edit3] Если тест терпит неудачу, то из-за вашей правовой ситуации невозможно реализовать монитор. Скажите своему боссу и позвольте ему принять решение об этом.
[Edit4] Googleing Оказался этот комментарий от отчета об ошибках:
Крючки не безопасны. Период. Что вы пытаетесь исправить?
Это является частью обсуждения с марта 2009 года о ошибке в LIBC / MALLOC / MALLOC.C
, которая содержит исправление. Так что, возможно, версия Glibc после эта дата работает, но, похоже, не является гарантией. Похоже, также зависит от вашей версии GCC.
Подстроки не являются перестановками. расчленить ()
последовательность, затем использовать два вложенных цикла вместе с array _ slice ()
для получения соответствующих элементов.
Во-первых, нельзя использовать элемент привязки в разделе < head >
. Во-вторых, вы уверены, что ваш путь CSS верен? Я спрашиваю, потому что у вас уже есть ссылка на css/newstyle.css
, но вы пытаетесь загрузить newstyle.css
. Вы уверены, что это не css/newstyle.css
?
Изменить: Здесь является рабочим примером собственного кода. Что-то еще не так. Попробуйте статически связать CSS и проверить, получаются ли стили. В противном случае в таблице стилей могут быть ошибки.
Статически связывая таблицу стилей, я хотел добавить это на вашу страницу вместо загрузки из javascript
<link rel="stylesheet" type="text/css" href="css/oldstyle.css" />
-121--2934032- У меня та же проблема. Я решил это на этом примере. Если мы не определяем THREAD_SAFE, у нас есть пример, приведенный человеком, и у нас есть ошибка сегментации. Если мы определяем THREAD_SAFE, мы не имеем ошибки сегментации.
#include <malloc.h>
#include <pthread.h>
#define THREAD_SAFE
#undef THREAD_SAFE
/** rqmalloc_hook_ */
static void* (*malloc_call)(size_t,const void*);
static void* rqmalloc_hook_(size_t taille,const void* appel)
{
void* memoire;
__malloc_hook=malloc_call;
memoire=malloc(taille);
#ifndef THREAD_SAFE
malloc_call=__malloc_hook;
#endif
__malloc_hook=rqmalloc_hook_;
return memoire;
}
/** rqfree_hook_ */
static void (*free_call)(void*,const void*);
static void rqfree_hook_(void* memoire,const void* appel)
{
__free_hook=free_call;
free(memoire);
#ifndef THREAD_SAFE
free_call=__free_hook;
#endif
__free_hook=rqfree_hook_;
}
/** rqrealloc_hook_ */
static void* (*realloc_call)(void*,size_t,const void*);
static void* rqrealloc_hook_(void* memoire,size_t taille,const void* appel)
{
__realloc_hook=realloc_call;
memoire=realloc(memoire,taille);
#ifndef THREAD_SAFE
realloc_call=__realloc_hook;
#endif
__realloc_hook=rqrealloc_hook_;
return memoire;
}
/** memory_init */
void memory_init(void)
{
malloc_call = __malloc_hook;
__malloc_hook = rqmalloc_hook_;
free_call = __free_hook;
__free_hook = rqfree_hook_;
realloc_call = __realloc_hook;
__realloc_hook = rqrealloc_hook_;
}
/** f1/f2 */
void* f1(void* param)
{
void* m;
while (1) {m=malloc(100); free(m);}
}
void* f2(void* param)
{
void* m;
while (1) {m=malloc(100); free(m);}
}
/** main */
int main(int argc, char *argv[])
{
memory_init();
pthread_t t1,t2;
pthread_create(&t1,NULL,f1,NULL);
pthread_create(&t1,NULL,f2,NULL);
sleep(60);
return(0);
}