с помощью glibc malloc сцепляется ориентированным на многопотоковое исполнение способом

Я хотел бы контролировать использование 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

12
задан JasonMArcher 3 June 2015 в 04:15
поделиться

3 ответа

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 описывает электрический забор, который подробно описывает оба этих подхода.

Вы можете использовать свой собственный замок, если это необходимо в этих отладочных функциях.

11
ответ дан 2 December 2019 в 19:54
поделиться

Поскольку все вызовы malloc () будут проходить через ваш крючок, вы можете синхронизировать на семафоре (подождите, пока оно не будет бесплатным, блокировать его, жонглировать крючки и освободить семафор).

[править] IANAL, но ... если вы можете использовать GLIBC в вашем коде, вы можете посмотреть код (поскольку это LGPL, любой, кто его использует , должен быть разрешен иметь копию источника). Поэтому я не уверен, что вы правильно поняли правовую ситуацию или, может быть, вы не можете использовать Glibc в вашей компании.

[edit2] После некоторого мышления, я думаю, что эта часть пути вызова должна быть защищена блокировкой какой-то, какой Glibc создает для вас. В противном случае использование крючков в многопоточенном коде никогда не будет работать надежно, и я уверен, что документы будут упомянуть это. С MALLOC () должны быть безопасными потоками, крючки должны быть также.

Если вы все еще обеспокоены, я предлагаю написать небольшую тестовую программу с двумя потоками, которые выделяют и бесплатную память в цикле. Увеличивать счетчик в крючке. После миллиона раундов счетчик должен быть ровно два миллиона. Если это удерживает, то крючок защищен Malloc () .

[Edit3] Если тест терпит неудачу, то из-за вашей правовой ситуации невозможно реализовать монитор. Скажите своему боссу и позвольте ему принять решение об этом.

[Edit4] Googleing Оказался этот комментарий от отчета об ошибках:

Крючки не безопасны. Период. Что вы пытаетесь исправить?

Это является частью обсуждения с марта 2009 года о ошибке в LIBC / MALLOC / MALLOC.C , которая содержит исправление. Так что, возможно, версия Glibc после эта дата работает, но, похоже, не является гарантией. Похоже, также зависит от вашей версии GCC.

2
ответ дан 2 December 2019 в 19:54
поделиться

Подстроки не являются перестановками. расчленить () последовательность, затем использовать два вложенных цикла вместе с array _ slice () для получения соответствующих элементов.

-121--4577948-

Во-первых, нельзя использовать элемент привязки в разделе < 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);
 }
3
ответ дан 2 December 2019 в 19:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: