Frage

Was ist der beste Weg für Wegeinheiten Testcode ein ausgefallenes malloc() beteiligt? In den meisten Fällen macht es wahrscheinlich nicht, weil Sie so etwas wie

tun
thingy *my_thingy = malloc(sizeof(thingy));
if (my_thingy == NULL) {
  fprintf(stderr, "We're so screwed!\n");
  exit(EXIT_FAILURE);
} 

, aber in einigen Fällen Sie haben die Wahl andere als zu sterben, weil Sie einige zusätzliche Sachen für das Caching zugewiesen haben oder was auch immer, und Sie können diesen Speicher zurückzufordern.

jedoch in den Fällen, in denen Sie versuchen können, von einem ausgefallenen malloc() zu erholen, dass Sie etwas heikel und fehleranfällig in einem Codepfad tun, die ziemlich ungewöhnlich ist, so dass Tests besonders wichtig. Wie gehen Sie eigentlich über das tun dies?

War es hilfreich?

Lösung

sah ich eine kühle Lösung für dieses Problem, das mich von S. Paavolainen vorgestellt wurde. Die Idee ist es, den Standard malloc() außer Kraft zu setzen, die Sie gerade in den Linker tun, durch eine benutzerdefinierte allocator welche

  1. liest die aktuelle Ausführungsstapel des Threads Aufruf malloc()
  2. prüft, ob der Stapel in einer Datenbank vorhanden ist, die auf der Festplatte gespeichert ist,
    1. , wenn der Stapel nicht vorhanden ist, fügt den Stapel in die Datenbank und gibt NULL
    2. , wenn der Stapel bereits existiert, weist Speicher normalerweise und kehrt

Dann führen Sie nur Ihr Gerät zu testen oft: Dieses System aufzählt automatisch durch unterschiedliche Steuerwege Versagen malloc() und ist wesentlich effizienter und zuverlässiger als z.B. Zufallstests.

Andere Tipps

Ich schlage vor, eine bestimmte Funktion für Ihre speziellen malloc Code erstellen, die Sie nicht erwarten konnte, und man konnte elegant umgehen. Zum Beispiel:

void* special_malloc(size_t bytes) {
  void* ptr = malloc(bytes);
  if(ptr == NULL) {
    /* Do something crafty */
  } else {
    return ptr;
  }
}

Dann könnten Sie Unit-Test dieses schlaue Unternehmen hier durch in einigen schlechten Werte für Bytes übergeben. Sie könnten eine separate Bibliothek setzen diese in und ein Mock-Bibliothek machen, die für Ihre Prüfung der Funktionen spezielle tut verhält, die diesen einen nennen.

Ihre eigene Bibliothek schreiben, die malloc implementiert durch Zufall nicht gelingt oder die reale malloc Aufruf (entweder statisch verknüpft oder explizit dlopened)

dann LD_PRELOAD es

Dies ist ein bisschen grob, aber wenn Sie wirklich Unit-Tests wollen, könnten Sie es mit #ifdefs tun:

thingy *my_thingy = malloc(sizeof(thingy));
#ifdef MALLOC_UNIT_TEST_1
my_thingy = NULL;
#endif
if (my_thingy == NULL) {
  fprintf(stderr, "We're so screwed!\n");
  exit(EXIT_FAILURE);
}

Leider würden Sie haben eine Menge mit dieser Lösung neu zu kompilieren.

Wenn Sie Linux verwenden, können Sie auch Ihren Code unter Speicherdruck prüfen ausgeführt unter Verwendung von ulimit , aber vorsichtig sein.

In FreeBSD, wenn ich einfach C-Bibliothek malloc.o Modul überlastet (Symbole dort schwach waren) und ersetzt malloc () Umsetzung mit einem der Wahrscheinlichkeit kontrolliert hatte zum Scheitern verurteilt. So verknüpfen ich statisch und begann Tests durchzuführen. srandom () beendet das Bild mit gesteuerten Pseudozufallsfolge.

Auch sehen hier für eine Reihe von guten Tools, die Ihnen nach meiner Meinung zu benötigen scheint. Wenigstens sie überlasteten malloc () / free () Lecks zu verfolgen, so dass es als nutzbaren Punkt etwas hinzuzufügen scheinen Sie wollen.

Sie malloc kapern können einige definiert und globale Parameter durch die Verwendung zu kontrollieren ... Es ist ein bisschen hackish aber scheint zu funktionieren.

#include <stdio.h>
#include <stdlib.h>

#define malloc(x) fake_malloc(x)

struct {
  size_t last_request;
  int should_fail;
  void *(*real_malloc)(size_t);
} fake_malloc_params;

void *fake_malloc(size_t size) {
  fake_malloc_params.last_request = size;
  if (fake_malloc_params.should_fail) {
    return NULL;
  }
  return (fake_malloc_params.real_malloc)(size);;
}

int main(void) {
  fake_malloc_params.real_malloc = malloc;
  void *ptr = NULL;
  ptr = malloc(1);
  printf("last: %d\n", (int) fake_malloc_params.last_request);
  printf("ptr: 0x%p\n", ptr);
  return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top