Fehler: free (): ungültige nächste Größe (schnell):

90

Was ist das für ein seltsamer Fehler, den ich bekomme? Ich kompiliere C ++ mit g ++ unter Ubuntu 10.10. Es erscheint zufällig, wenn ich die ausführbare Datei ausführe (vielleicht 2 Mal in 8 Stunden, mit 10 Kompilierungen pro Stunde). Wenn ich jedoch sauber mache und neu kompiliere, verschwindet es die meiste Zeit.

*** glibc detected *** ./emailQueue.app: free(): invalid next size (fast): 0x0000000001c40270 ***
======= Backtrace: =========
/lib/libc.so.6(+0x774b6)[0x7f490d95e4b6]
/lib/libc.so.6(cfree+0x73)[0x7f490d964c83]
./emailQueue.app[0x401f47]
/lib/libc.so.6(__libc_start_main+0xfe)[0x7f490d905d8e]
./emailQueue.app[0x401cc9]
======= Memory map: ========
00400000-0040d000 r-xp 00000000 08:01 1311132                            /home/server/Projects/email/emailQueue.app
0060d000-0060e000 r--p 0000d000 08:01 1311132                            /home/server/Projects/email/emailQueue.app
0060e000-0060f000 rw-p 0000e000 08:01 1311132                            /home/server/Projects/email/emailQueue.app
01c40000-01c82000 rw-p 00000000 00:00 0                                  [heap]
7f4908000000-7f4908021000 rw-p 00000000 00:00 0 
7f4908021000-7f490c000000 ---p 00000000 00:00 0 
7f490ce52000-7f490ce5e000 r-xp 00000000 08:01 1051251                    /lib/libnss_files-2.12.1.so
7f490ce5e000-7f490d05d000 ---p 0000c000 08:01 1051251                    /lib/libnss_files-2.12.1.so
7f490d05d000-7f490d05e000 r--p 0000b000 08:01 1051251                    /lib/libnss_files-2.12.1.so
7f490d05e000-7f490d05f000 rw-p 0000c000 08:01 1051251                    /lib/libnss_files-2.12.1.so
7f490d05f000-7f490d075000 r-xp 00000000 08:01 1048770                    /lib/libz.so.1.2.3.4
7f490d075000-7f490d275000 ---p 00016000 08:01 1048770                    /lib/libz.so.1.2.3.4
7f490d275000-7f490d276000 r--p 00016000 08:01 1048770                    /lib/libz.so.1.2.3.4
7f490d276000-7f490d277000 rw-p 00017000 08:01 1048770                    /lib/libz.so.1.2.3.4
7f490d277000-7f490d28e000 r-xp 00000000 08:01 1051248                    /lib/libnsl-2.12.1.so
7f490d28e000-7f490d48d000 ---p 00017000 08:01 1051248                    /lib/libnsl-2.12.1.so
7f490d48d000-7f490d48e000 r--p 00016000 08:01 1051248                    /lib/libnsl-2.12.1.so
7f490d48e000-7f490d48f000 rw-p 00017000 08:01 1051248                    /lib/libnsl-2.12.1.so
7f490d48f000-7f490d491000 rw-p 00000000 00:00 0 
7f490d491000-7f490d49a000 r-xp 00000000 08:01 1051244                    /lib/libcrypt-2.12.1.so
7f490d49a000-7f490d69a000 ---p 00009000 08:01 1051244                    /lib/libcrypt-2.12.1.so
7f490d69a000-7f490d69b000 r--p 00009000 08:01 1051244                    /lib/libcrypt-2.12.1.so
7f490d69b000-7f490d69c000 rw-p 0000a000 08:01 1051244                    /lib/libcrypt-2.12.1.so
7f490d69c000-7f490d6ca000 rw-p 00000000 00:00 0 
7f490d6ca000-7f490d6e2000 r-xp 00000000 08:01 1051256                    /lib/libpthread-2.12.1.so
7f490d6e2000-7f490d8e1000 ---p 00018000 08:01 1051256                    /lib/libpthread-2.12.1.so
7f490d8e1000-7f490d8e2000 r--p 00017000 08:01 1051256                    /lib/libpthread-2.12.1.so
7f490d8e2000-7f490d8e3000 rw-p 00018000 08:01 1051256                    /lib/libpthread-2.12.1.so
7f490d8e3000-7f490d8e7000 rw-p 00000000 00:00 0 
7f490d8e7000-7f490da61000 r-xp 00000000 08:01 1048743                    /lib/libc-2.12.1.so
7f490da61000-7f490dc60000 ---p 0017a000 08:01 1048743                    /lib/libc-2.12.1.so
7f490dc60000-7f490dc64000 r--p 00179000 08:01 1048743                    /lib/libc-2.12.1.so
7f490dc64000-7f490dc65000 rw-p 0017d000 08:01 1048743                    /lib/libc-2.12.1.so
7f490dc65000-7f490dc6a000 rw-p 00000000 00:00 0 
7f490dc6a000-7f490dc7f000 r-xp 00000000 08:01 1048655                    /lib/libgcc_s.so.1
7f490dc7f000-7f490de7e000 ---p 00015000 08:01 1048655                    /lib/libgcc_s.so.1
7f490de7e000-7f490de7f000 r--p 00014000 08:01 1048655                    /lib/libgcc_s.so.1
7f490de7f000-7f490de80000 rw-p 00015000 08:01 1048655                    /lib/libgcc_s.so.1
7f490de80000-7f490df02000 r-xp 00000000 08:01 1051246                    /lib/libm-2.12.1.so
7f490df02000-7f490e101000 ---p 00082000 08:01 1051246                    /lib/libm-2.12.1.so
7f490e101000-7f490e102000 r--p 00081000 08:01 1051246                    /lib/libm-2.12.1.so
7f490e102000-7f490e103000 rw-p 00082000 08:01 1051246                    /lib/libm-2.12.1.so
7f490e103000-7f490e1eb000 r-xp 00000000 08:01 4853329                    /usr/lib/libstdc++.so.6.0.14
7f490e1eb000-7f490e3ea000 ---p 000e8000 08:01 4853329                    /usr/lib/libstdc++.so.6.0.14
7f490e3ea000-7f490e3f2000 r--p 000e7000 08:01 4853329                    /usr/lib/libstdc++.so.6.0.14
7f490e3f2000-7f490e3f4000 rw-p 000ef000 08:01 4853329                    /usr/lib/libstdc++.so.6.0.14
7f490e3f4000-7f490e409000 rw-p 00000000 00:00 0 
7f490e409000-7f490e5c7000 r-xp 00000000 08:01 4851315                    /usr/lib/libmysqlclient.so.16.0.0
7f490e5c7000-7f490e7c7000 ---p 001be000 08:01 4851315                    /usr/lib/libmysqlclient.so.16.0.0
7f490e7c7000-7f490e7cc000 r--p 001be000 08:01 4851315                    /usr/lib/libmysqlclient.so.16.0.0
7f490e7cc000-7f490e816000 rw-p 001c3000 08:01 4851315                    /usr/lib/libmysqlclient.so.16.0.0
7f490e816000-7f490e817000 rw-p 00000000 00:00 0 
7f490e817000-7f490e837000 r-xp 00000000 08:01 1048597                    /lib/ld-2.12.1.so
7f490ea15000-7f490ea1c000 rw-p 00000000 00:00 0 
7f490ea33000-7f490ea37000 rw-p 00000000 00:00 0 
7f490ea37000-7f490ea38000 r--p 00020000 08:01 1048597                    /lib/ld-2.12.1.so
7f490ea38000-7f490ea39000 rw-p 00021000 08:01 1048597                    /lib/ld-2.12.1.so
7f490ea39000-7f490ea3a000 rw-p 00000000 00:00 0 
7fffb85b9000-7fffb85da000 rw-p 00000000 00:00 0                          [stack]
7fffb85ff000-7fffb8600000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted
Josh
quelle
1
Ein fehlendes Semikolon hat diesen Fehler für mich verursacht.
Atzol

Antworten:

105

Dies bedeutet, dass Sie einen Speicherfehler haben. Sie können zu versuchen , freeeinen Zeiger, der nicht durch zugewiesen wurde malloc(oder deleteein Objekt , das nicht erstellt wurde new) , oder Sie können versuchen , free/ deletemehr als einmal ein solches Objekt. Möglicherweise wird ein Puffer überfüllt oder auf andere Weise in den Speicher geschrieben, in den Sie nicht schreiben sollten, was zu einer Beschädigung des Heapspeichers führt.

Eine beliebige Anzahl von Programmierfehlern kann dieses Problem verursachen. Sie müssen einen Debugger verwenden, eine Rückverfolgung abrufen und sehen, was Ihr Programm tut, wenn der Fehler auftritt. Wenn dies fehlschlägt und Sie feststellen, dass Sie den Heap zu einem früheren Zeitpunkt beschädigt haben, kann es zu schmerzhaftem Debugging kommen (es ist möglicherweise nicht zu schmerzhaft, wenn das Projekt klein genug ist, um es Stück für Stück anzugehen).

James McNellis
quelle
37
Tools wie valgrind sind sehr hilfreich, um die Ursache dieser Fehlerarten zu finden. Stellen Sie einfach sicher, dass Sie mit Debugging-Symbolen kompilieren.
Daniel Gallagher
3
Zu Ihrer Information: Ich hatte dies, nachdem ich die Größe eines std :: vector <> geändert hatte und er nicht groß genug war.
Adam27X
1
"Ja wirklich?" Sie haben ein Problem mit free (), wenn der Vektor nicht groß genug war. Lesen Sie zumindest zuerst die Frage.
user2407394
21

Ich habe das gleiche Problem festgestellt, obwohl ich in meinem Programm keine dynamische Speicherzuweisung vorgenommen habe, aber auf den Index eines Vektors zugegriffen habe, ohne dafür Speicher zuzuweisen. Wenn dies der gleiche Fall ist, sollten Sie mithilfe von Vektorelementen besser Speicher zuweisen resize()und dann darauf zugreifen.

vvs14
quelle
7

Wir brauchen den Code, aber dieser wird normalerweise angezeigt, wenn Sie versuchen, free()von einem nicht zugewiesenen Zeiger aus zu speichern. Dies passiert oft, wenn Sie doppelt befreien.

orlp
quelle
6

Wenn Sie versuchen, Speicherplatz für ein Array von Zeigern zuzuweisen, z

char** my_array_of_strings;  // or some array of pointers such as int** or even void**

Dann müssen Sie die Wortgröße berücksichtigen (8 Byte in einem 64-Bit-System, 4 Byte in einem 32-Bit-System), wenn Sie Platz für n Zeiger zuweisen. Die Größe eines Zeigers entspricht Ihrer Wortgröße.

Während Sie also möglicherweise Platz für n Zeiger zuweisen möchten, benötigen Sie tatsächlich n mal 8 oder 4 (für 64-Bit- bzw. 32-Bit-Systeme).

So vermeiden Sie ein Überlaufen des zugewiesenen Speichers für n Elemente mit 8 Byte:

my_array_of_strings = (char**) malloc( n * 8 );  // for 64-bit systems
my_array_of_strings = (char**) malloc( n * 4 );  // for 32-bit systems

Dies gibt einen Block mit n Zeigern zurück, die jeweils aus 8 Bytes bestehen (oder 4 Bytes, wenn Sie ein 32-Bit-System verwenden).

Ich habe festgestellt, dass Linux es Ihnen ermöglicht, alle n Zeiger zu verwenden, wenn Sie die Wortgröße nicht kompensiert haben, aber wenn Sie versuchen, diesen Speicher freizugeben, erkennt es seinen Fehler und gibt diesen ziemlich bösen Fehler aus. Und es ist schlecht, wenn Sie den zugewiesenen Speicher überlaufen, warten viele Sicherheitsprobleme auf Sie.

George
quelle
2
Wir können den gleichen Code für jedes System generisch machen, indem wir nicht 4 oder 8 Bytes mit fest codieren sizeof(char*).
Ben G.
sizeofWenn Sie den Operator nicht verwenden , wenn Sie malloc verwenden, müssen Sie nur um Probleme bitten. IIRC, der Standard, garantiert die Größe eines Zeichens, aber so ziemlich alles andere hängt von der ISA ab, sodass Sie wirklich sizeofüberall am besten sind.
Ajxs
1

Ich bin auf eine solche Situation gestoßen, in der Code die API von STL umging und unsicher in das Array schrieb, wenn jemand die Größe ändert. Das Hinzufügen der Behauptung hier hat es gefangen:

void Logo::add(const QVector3D &v, const QVector3D &n)
{
 GLfloat *p = m_data.data() + m_count;
 *p++ = v.x();
 *p++ = v.y();
 *p++ = v.z();
 *p++ = n.x();
 *p++ = n.y();
 *p++ = n.z();
 m_count += 6;
 Q_ASSERT( m_count <= m_data.size() );
}
Peter Karasev
quelle
1

Ich habe einen ähnlichen Fehler festgestellt. Es war ein Noob-Fehler, der in Eile begangen wurde. Ganzzahliges Array, ohne die Größe int a [] zu deklarieren und dann zu versuchen, darauf zuzugreifen. Der C ++ - Compiler hätte einen solchen Fehler leicht abfangen sollen, wenn er in main gewesen wäre. Da dieses bestimmte int-Array jedoch in einem Objekt deklariert wurde, wurde es gleichzeitig mit meinem Objekt erstellt (viele Objekte wurden erstellt) und der Compiler gab einen freien (): ungültigen (normalen) Fehler der nächsten Größe aus. Ich dachte an 2 Erklärungen dafür (bitte klären Sie mich auf, wenn jemand mehr weiß): 1.) Dies führte dazu, dass ihm ein zufälliger Speicher zugewiesen wurde, aber da dieser nicht zugänglich war, wurde der gesamte andere Heap-Speicher freigegeben, der nur versucht wurde, ihn zu finden diese int. 2.) Der dafür benötigte Speicher war für ein Programm praktisch unendlich und um dies zuzuweisen, wurde der gesamte andere Speicher freigegeben.

Eine einfache:

    int* a;
    class foo{ 
    foo(){
       for(i=0;i<n;i++)
           a=new int[i];
     }

Problem gelöst. Der Versuch, dies zu debuggen, hat jedoch viel Zeit in Anspruch genommen, da der Compiler den Fehler nicht "wirklich" finden konnte.

Arkantos
quelle