Frage

Ich mag die Verwendung von mallocs und befreit in einer Anwendung überwachen, indem die malloc und free Haken.

Hier ist die Dokumentation http: // www. gnu.org/s/libc/manual/html_node/Hooks-for-Malloc.html

Aus dem Beispiel-Seite, dass my_malloc_hook vorübergehend die malloc Haken Aus-Schalter sehen können (oder zum vorherigen Haken in der Kette) vor dem erneuten Aufruf malloc.

Dies ist ein Problem bei der Überwachung von Anwendungen mit mehreren Threads (Ende Frage Erläuterung siehe).

Weitere Beispiele für die Verwendung von malloc Haken, die ich im Internet gefunden habe, haben das gleiche Problem.

Gibt es eine Möglichkeit, diese Funktion neu schreiben korrekt in einer Multi-Thread-Anwendung arbeiten?

Zum Beispiel gibt es eine interne libc-Funktion, dass die malloc Haken aufrufen kann, dass die Zuordnung abgeschlossen ist, ohne die Notwendigkeit, meine Haken zu deaktivieren.

Ich kann nicht an der libc Quellcode aussehen aufgrund von Corporate Rechtspolitik, so kann die Antwort klar sein.

Meine Design-Spezifikation sagt, dass ich nicht malloc mit einem anderen malloc Design ersetzen kann.

Ich kann davon ausgehen, dass keine andere Haken im Spiel sind.


UPDATE

Da die malloc Haken vorübergehend entfernt werden, während die malloc Wartung, ein anderer Thread malloc nennen kann und nicht den Haken bekommen.

Es wurde vorgeschlagen, dass malloc eine große Sperre um es hat, dass dies nicht passiert verhindert, aber es ist nicht dokumentiert, und die Tatsache, dass ich rekursiv malloc effektiv schlägt rufen jede Sperre entweder muss nach dem Haken vorhanden sind, oder sein jolly clever:

caller -> 
  malloc -> 
    malloc-hook (disables hook) -> 
      malloc -> # possible hazard starts here
        malloc_internals
      malloc <-
    malloc-hook (enables hook) <-
  malloc
caller
War es hilfreich?

Lösung

AKTUALISIERT

Sie sind Recht nicht __malloc_hooks vertrauen; Ich habe den Code einen Blick zu, und sie sind - staggeringly crazily -. Nicht Thread-sicher

die geerbten Haken direkt aufrufen, anstatt die Wiederherstellung und Wiedereintritt in malloc, scheint aus dem Dokument zu abweichenden Sie zitieren ein wenig zu viel, um sich wohl fühlen lässt.

http://manpages.sgvulcan.com/malloc_hook.3.php :

  

Hakengrößen werden nicht Thread-sicher, so dass sie jetzt veraltet sind. Programmierer sollten stattdessen Anrufe an die entsprechenden Funktionen preempt durch die Definition und Export-Funktionen wie „malloc“ und „frei“.

Der geeignete Weg debug malloc / realloc / Frei Funktionen zu injizieren ist Ihre eigene Bibliothek, die Ihren ‚debug‘ Versionen dieser Funktionen exportiert, und schiebt sich dann auf die wirklichen. C Verknüpfung wird in explizitem Auftrag erledigt, so dass, wenn zwei Bibliotheken die gleiche Funktion zur Verfügung stellt, wird die erste angegebenen verwendet. Sie können auch Ihre malloc während der Ladezeit auf Unix mit den LD_PRELOAD Mechanismen injizieren.

http://linux.die.net/man/3/efence beschreibt Electric Fence, die beide diese Ansätze Details.

Sie können Ihre eigene Verriegelung, wenn in diesen Debug-Funktionen verwenden, wenn dies erforderlich ist.

Andere Tipps

Ich habe das gleiche Problem. Ich habe es mit diesem Beispiel gelöst. Wenn wir THREAD_SAFE nicht definieren, haben wir das Beispiel von dem Mann gegeben, und wir haben einen Segmentierungsfehler. Wenn wir THREAD_SAFE definieren, haben wir keine Segmentierung Fehler.

#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);
 }

Da alle Anrufe auf malloc () wird den Haken gehen, Sie auf einer Semaphore synchronisieren kann (warten, bis sie frei ist, es sperren, jonglieren die Haken und gratis das Semaphore).

[EDIT] IANAL aber ... Wenn Sie verwenden glibc in Ihrem Code, dann können Sie den Code anschauen (da es LGPL ist, jemand mit ihm muss dürfen eine Kopie der Quelle haben). So bin ich nicht sicher, ob Sie die rechtliche Situation richtig verstanden oder vielleicht sind Sie rechtlich nicht glibc von Ihrem Unternehmen zu nutzen.

[EDIT 2] Nach einiger Überlegung, ich denke, dass dieser Teil des Verbindungsweges müssen durch eine Sperre von einer Art geschützt werden, die glibc für Sie erstellt. Andernfalls würden mit Haken in Multi-Threaded-Code nie zuverlässig arbeiten, und ich bin sicher, dass die Dokumentation diesen erwähnen würde. Da malloc() Thread-sicher sein müssen, müssen die Haken auch sein.

Wenn Sie immer noch besorgt sind, dann schlage ich vor, ein kleines Testprogramm mit zwei Threads zu schreiben, und die freien Speicher in einer Schleife zugeordnet werden. Inkrementieren eines Zählers in dem Haken. Nach einer Million Runden soll der Zähler genau zwei Millionen sein. Wenn dies zutrifft, dann der Haken als auch durch die malloc() Sperre geschützt ist.

[EDIT3] Wenn der Test fehlschlägt, dann, wegen Ihrer rechtlichen Situation, dann ist es nicht möglich, den Monitor zu implementieren. Sagen Sie Ihren Chef und läßt ihn eine Entscheidung darüber machen.

[Edit4] googeln diesen Kommentar von einem Bug-Report aufgedreht:

  

Die Haken sind nicht Thread-sicher. Zeitraum. Was versuchen Sie zu beheben?

Dies ist Teil einer Diskussion ab März 2009 über einen Fehler in libc/malloc/malloc.c, die ein Update enthält. Also vielleicht eine Version von glibc nach Dieses Datum funktioniert, aber es scheint nicht eine Garantie zu sein. Es scheint auch auf Ihrer Version von GCC abhängig zu sein.

Es gibt keine Möglichkeit, die malloc Haken in einer Thread-sichere Art und Weise zu verwenden, während in malloc Rekursion. Die Schnittstelle ist schlecht konzipiert, wahrscheinlich nicht mehr zu reparieren.

Auch wenn Sie einen Mutex in Ihrem Haken Code zu setzen, das Problem ist, dass in malloc ruft nicht jene Schleusen sehen erst, nachdem sie durch den Hakenmechanismus vergangen sind, und durch den Hakenmechanismus passieren, schauen sie auf globale Variablen ( die Haken Zeiger) ohne Ihre Mutex zu erwerben. Wie Sie Speichern, Ändern und Wiederherstellung dieser Zeiger in einem Thread, allocator Anrufe in einem anderen Thread von ihnen beeinflusst werden.

  

Das wichtigste Design-Problem ist, dass der Haken Null-Zeiger standardmäßig sind. Wenn die Schnittstelle einfach nicht-Null-Standard-Haken versehen, die die Zuordnungs geeignet sind (die unterste Ebene allocator die keine mehr Haken nicht nennen), dann wäre es einfach und sicher sein Haken hinzuzufügen: Sie gerade die vorherigen Haken retten könnte, und in den neuen Haken, Rekursion in malloc durch den Haltehaken aufrufen, ohne mit irgendwelchen globalen Zeiger (außer an Haken Installationszeit, die vor allen Threads getan werden kann, starten) Hantieren.

     

Alternativ glibc könnte eine interne malloc Schnittstelle bereitzustellen, die nicht die Haken nicht aufrufen.

     

Ein weiterer vernünftiger Entwurf wäre die Verwendung von lokalen Thread-Speicher für den Haken sein. Aufschalten und einen Haken würde die Wiederherstellung in einem Thread durchgeführt werden, ohne Störung der von einem anderen Thread gesehen Haken.

Wie es aussieht, was Sie tun können, die glibc malloc Haken zu verwenden ist sicher Rekursion in malloc zu vermeiden. Sie nicht die Haken Zeiger innerhalb der Haken Rückrufe ändern, und einfach Ihr eigenes allocator nennen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top