Frage

Ich implementiere einen Klassifik- und Eroberungspolynomalgorithmus, damit ich ihn gegen eine OpenCL -Implementierung befriedigen kann, aber ich kann nicht bekommen malloc arbeiten. Wenn ich das Programm ausführe, verteilt es eine Reihe von Sachen, überprüft einige Dinge und sendet dann die size/2 zum Algorithmus. Dann, wenn ich die schlage malloc Zeile wieder ausspuckt dies:

malloc.c: 3096: malloc_chunk, fd)))) && old_size == 0) || ((nicht signiert lang) (old_size)> = (unsigniert lang) ((((__ __ __ __ __ busingin_offsetof (size_t))) - 1)))) && ((old_top) -> Größe & 0x1) && ((nicht signiert long) old_end & pagemask) == 0) 'fehlgeschlagen. Abgebrochen

Die fragliche Zeile lautet:

int *mult(int size, int *a, int *b) {
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
    fprintf(stdout, "size: %d\n", size);

    out = (int *)malloc(sizeof(int) * size * 2);
}

Ich habe die Größe mit einem überprüft fprintf, und es ist eine positive Ganzzahl (normalerweise 50 zu diesem Zeitpunkt). Ich habe versucht anzurufen malloc Mit einer einfachen Zahl auch und ich bekomme immer noch den Fehler. Ich bin nur verblüfft darüber, was los ist, und nichts von Google, das ich bisher gefunden habe, ist hilfreich.

Irgendwelche Ideen, was ist los? Ich versuche herauszufinden, wie man ein neueres GCC zusammenstellt, falls es ein Compiler -Fehler ist, aber ich bezweifle es wirklich.

War es hilfreich?

Lösung

99,9% wahrscheinlich, dass Sie das Gedächtnis beschädigt haben (über- oder untergeflüssiges Puffer, schrieb an einen Zeiger, nachdem er befreit wurde, zweimal auf demselben Zeiger usw. frei genannt wurde.)

Führen Sie Ihren Code unter Valgrind Um zu sehen, wo Ihr Programm etwas falsch gemacht hat.

Andere Tipps

Um Ihnen ein besseres Verständnis von zu geben warum Dies passiert, ich möchte auf @R-Samuel-Klatchkos Antwort ein wenig erweitern.

Wenn du anrufst malloc, Was wirklich passiert, ist etwas komplizierter, als nur ein Stück Erinnerung zu geben, mit dem Sie spielen können. Unter der Haube, malloc Hält auch einige Haushaltsinformationen über das Gedächtnis, das es Ihnen gegeben hat (vor allem seine Größe), sodass Sie beim Anruf free, Es weiß Dinge, wie viel Gedächtnis, um frei zu sein. Diese Informationen werden üblicherweise kurz vor dem Speicherort aufbewahrt, der Ihnen von Ihnen zurückgegeben wird malloc. Ausführlichere Informationen finden Sie im Internet ™, aber die (sehr) Grundidee ist ungefähr so:

+------+-------------------------------------------------+
+ size |                  malloc'd memory                +
+------+-------------------------------------------------+
       ^-- location in pointer returned by malloc

Aufbauend darauf (und die Dinge stark vereinfachen), wenn Sie anrufen malloc, Es muss einen Zeiger auf den nächsten Teil des Speichers bringen, der verfügbar ist. Eine sehr einfache Möglichkeit, dies zu tun size Bytes weiter unten (oder nach oben) im Speicher. Mit dieser Implementierung sieht Ihr Gedächtnis nach der Zuordnung so etwas aus p1, p2 und p3:

+------+----------------+------+--------------------+------+----------+
+ size |                | size |                    | size |          +
+------+----------------+------+--------------------+------+----------+
       ^- p1                   ^- p2                       ^- p3

Was verursacht also Ihren Fehler?

Stellen Sie sich vor, Ihr Code schreibt fälschlicherweise über die Menge an Speicher, die Sie zugewiesen haben (entweder weil Sie weniger zugewiesen haben als Sie benötigt haben, wie Ihr Problem war oder weil Sie die falschen Grenzbedingungen irgendwo in Ihrem Code verwenden). Sagen Sie, Ihr Code schreibt so viele Daten zu p2 Dass es überschreibt, was sich befindet p3's size aufstellen. Wenn Sie jetzt den nächsten Anruf anrufen malloc, Es wird sich auf den letzten Speicherort ansehen, den es zurückgegeben hat, schauen Sie sich das Feld der Größe an, wechseln Sie zu zu p3 + size und dann beginnen Sie von dort aus dem Gedächtnis zuzuweisen. Da hat Ihr Code überschrieben size, Dieser Speicherort erfolgt jedoch nicht mehr nach dem zuvor zugewiesenen Speicher.

Unnötig zu erwähnen, dass das Chaos zerstören kann! Die Implementierer von malloc haben daher eine Reihe von "Behauptungen" oder Schecks eingerichtet, die versuchen, eine Reihe von geistigen Gesundheit zu überprüfen, um dies (und andere Probleme) zu fangen, wenn sie kurz vor der Tür stehen. In Ihrem speziellen Fall werden diese Behauptungen verletzt und so malloc Abburns und Ihnen sagen, dass Ihr Code etwas tun würde, um etwas zu tun, das es wirklich nicht tun sollte.

Wie bereits erwähnt, handelt es sich um eine grobe Unvereinbarkeit, aber es reicht aus, um den Punkt zu veranschaulichen. Die GLIBC -Implementierung von malloc Es ist mehr als 5K -Linien, und es gab erhebliche Untersuchungen darüber, wie gute Mechanismen für dynamische Speicherzuordnungen aufgebaut werden können. Es ist also nicht möglich, alles in einer SO -Antwort abzudecken. Hoffentlich hat dies Ihnen jedoch einen Blick darauf gegeben, was das Problem wirklich verursacht!

Meine alternative Lösung zur Verwendung von Valgrind:

Ich bin sehr glücklich, weil ich nur meinem Freund geholfen habe, ein Programm zu debuggen. Sein Programm hatte genau dieses Problem (malloc() Abbruch verursachen) mit der gleichen Fehlermeldung von GDB.

Ich habe sein Programm verwendet Adresse Desinfektionsmittel mit

gcc -Wall -g3 -fsanitize=address -o new new.c
              ^^^^^^^^^^^^^^^^^^

Und rannte dann gdb new. Wenn das Programm von beendet wird SIGABRT in einem nachfolgenden Ursachen verursacht malloc(), Es werden viele nützliche Informationen gedruckt:

=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
    #0 0x7ffffe49ed19  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
    #1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)

0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
    #0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Schauen wir uns die Ausgabe an, insbesondere die Stapelspur:

Der erste Teil besagt, dass es einen ungültigen Schreibvorgang bei new.c:59. Diese Zeile liest sich

memset(len,0,sizeof(int*)*p);
             ^^^^^^^^^^^^

Der zweite Teil besagt, dass das Gedächtnis, auf dem das schlechte Schreiben stattgefunden hat new.c:55. Diese Zeile liest sich

if(!(len=(int*)malloc(sizeof(int)*p))){
                      ^^^^^^^^^^^

Das ist es. Ich brauchte nur weniger als eine halbe Minute, um den Fehler zu finden, der meinen Freund für ein paar Stunden verwirrte. Er hat es geschafft, den Fehler zu finden, aber es ist nachfolgend malloc() Nennen Sie das fehlgeschlagen, ohne diesen Fehler im vorherigen Code entdecken zu können.

Summe: Versuchen Sie die -fsanitize=address von GCC oder Klang. Es kann sehr hilfreich sein, wenn Gedächtnisprobleme debuggen.

Sie werden wahrscheinlich irgendwo über das zugewiesene Mem hinaus überrannt. Dann nimmt das zugrunde liegende SW erst auf, wenn Sie Malloc anrufen

Es kann einen Wachwert geben, der von Malloc gefangen wird.

Bearbeiten ... fügte dies für Grenzen hinzu, um Hilfe zu überprüfen

http://www.lrde.epita.fr/~akim/ccmp/doc/bound-checking.html

Ich habe die folgende Nachricht erhalten, ähnlich wie Sie:

    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.

Machte einen Fehler, der bei der Verwendung von Malloc eine Methode angerufen hat. Das Multiplikationszeichen '*' mit einem '+' fälschlicherweise überschreibt, wenn der Faktor nach sizeof ()-Bediener beim Hinzufügen eines Feldes zu einem vorzeichenlosen Zeichen-Array aktualisiert wird.

Hier ist der Code, der für den Fehler in meinem Fall verantwortlich ist:

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5);
    b[INTBITS]=(some calculation);
    b[BUFSPC]=(some calculation);
    b[BUFOVR]=(some calculation);
    b[BUFMEM]=(some calculation);
    b[MATCHBITS]=(some calculation);

In einer anderen Methode später habe ich Malloc erneut verwendet und die oben gezeigte Fehlermeldung erstellt. Der Anruf war (einfach genug):

    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50);

Denken Sie mit dem '+'-Zeichen beim 1. Aufruf an, der zu Misculus in Kombination mit der sofortigen Initialisierung des Arrays nach dem Abschreiben (Überschreiben, das dem Array nicht zugeordnet wurde), die Verwirrung der MALOC-Speicherkarte mit sich gebracht hat. Deshalb ging der 2. Anruf schief.

Wir haben diesen Fehler bekommen, weil wir vergessen haben, uns mit Sizeof (int) zu multiplizieren. Beachten Sie, dass das Argument für Malloc (..) eine Reihe von Bytes ist, nicht die Anzahl der maschinellen Wörter oder was auch immer.

Ich habe eine Anwendung von Visual C nach GCC über Linux portiert und hatte das gleiche Problem mit

malloc.c: 3096: sysmalloc: Behauptung mit GCC auf Ubuntu 11.

Ich habe den gleichen Code in eine Suse -Verteilung (auf anderen Computer) verschoben und habe kein Problem.

Ich vermute, dass die Probleme nicht in unseren Programmen, sondern in der eigenen LIBC sind.

Ich habe das gleiche Problem bekommen, Malloc habe N wieder in einer Schleife zum Hinzufügen neuer Zeichen für Zeichenfolgen verwendet. Ich hatte das gleiche Problem, aber nachdem ich den zugewiesenen Speicher veröffentlicht hatte void free() Das Problem wurde sortiert

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