Linux C++ Programm stürzt mit St9bad_alloc nach map wird sehr groß

Ich bin mit einem C++ - Programm, dass die Einbeziehung der Gebäude invertierten index auf red hat linux 64 bit. Meine invert-index ist definiert als map<unsigned long long int, map<int,int> > invertID; und ich habe diesen Fehler, wo es stürzt ab nach dem Zufallsprinzip, mit what(): St9bad_alloc.Jedes mal, wenn der crash ist anders. Manchmal, ich habe 100,000,000 keys und es läuft noch eine Weile mehr. Manchmal, etwa 80.000.000 liegt-Tasten, und schon Schreien die Fehler.

Googeln um, ich fand, dass dieser Fehler kann kommen von new, aber ein Blick auf meinen code, ich bin nicht mit jedem new Stichwort, doch, ich habe solche Speicherzuweisung mit Karte. Ich immer wieder einfügen in das Schlüssel/Wert-paar in jeder iteration. Also beschloss ich einige experiment mit try catch - Anweisung.

In der Tat, hier ist der kritische Teil des Codes und der Ausgabe:

    map<unsigned long long int, map<int,int> >::iterator mainMapIt = invertID.find(ID);
    if (mainMapIt != invertID.end()){
    //if this ImageID key exists in InvID sub-map
        map<int,int> M = mainMapIt->second; //THIS IS LINE 174.
        map<int,int>::iterator subMapIt = M.find(imageID);
        if (subMapIt != M.end()){
        //increment the number of this ImageID key
            ++invertID[ID][imageID];
        }
        else{
        //add ImageID key with value 1 into the InvertID
            try{
                invertID[ID][imageID] = 1;
                ++totalPushBack;
            }catch (bad_alloc ba){
                cout << "CAUGHT 1: invertID[" << ID << "][" << imageID << endl;
            }
        }
    }
    else{
    //create the first empty map with the key as image ID with value 1 and put it in implicitly to the invertID
        try{
            invertID[ID][imageID] = 1;
        }catch (bad_alloc ba){
            cout << "CAUGHT 2: invertID[" << ID << "][" << imageID << endl;
        }
    }

Ausgabe:

...
CAUGHT 2: invertID[21959247897][3856
CAUGHT 2: invertID[38022506156][3856
CAUGHT 2: invertID[29062506144][3856
terminate called after throwing an instance of 'std::bad_alloc'
  what():  St9bad_alloc

Sehe ich, dass, wenn ich versuchte, fügen Sie neue Schlüssel, der Fehler ausgelöst wird. Jedoch, bekam ich ein bisschen mehr überraschung, dass St9bad_alloc ist noch nicht geworfen, nachdem ich die Abdeckung der Schlüssel einlegen Teil mit try catch block. Ich habe ein wenig backtrace und hier ist das Ergebnis:

(gdb) backtrace
#0  0x000000344ac30265 in raise () from /lib64/libc.so.6
#1  0x000000344ac31d10 in abort () from /lib64/libc.so.6
#2  0x00000034510becb4 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6
#3  0x00000034510bcdb6 in ?? () from /usr/lib64/libstdc++.so.6
#4  0x00000034510bcde3 in std::terminate() () from /usr/lib64/libstdc++.so.6
#5  0x00000034510bceca in __cxa_throw () from /usr/lib64/libstdc++.so.6
#6  0x00000034510bd1d9 in operator new(unsigned long) () from /usr/lib64/libstdc++.so.6
#7  0x0000000000406544 in __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<int const, int> > >::allocate (
    this=0x7fffffffdfc0, __n=1)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/ext/new_allocator.h:88
#8  0x0000000000406568 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_get_node (this=0x7fffffffdfc0)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:358
#9  0x0000000000406584 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_create_node (this=0x7fffffffdfc0, __x=...)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:367
#10 0x00000000004065e3 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_clone_node (this=0x7fffffffdfc0, __x=0x21c082bd0)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:381
#11 0x0000000000406634 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_M_copy (this=0x7fffffffdfc0, __x=0x21c082bd0, __p=0x7fffffffdfc8)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:1226
#12 0x00000000004067e9 in std::_Rb_tree<int, std::pair<int const, int>, std::_Select1st<std::pair<int const, int> >, std::less<int>, std::allocator<std::pair<int const, int> > >::_Rb_tree (this=0x7fffffffdfc0, __x=...)
    at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:570
#13 0x0000000000406885 in std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >::map (
    this=0x7fffffffdfc0, __x=...) at /usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:175
#14 0x0000000000403039 in generateInvertID (pathToPF=0x6859a8 "/home/karl/c/000605.pf",
    pathToC=0x38c139ed8 "/home/karl/c/000605.c", imageID=3856)
    at InvertIndexGen.cpp:174
#15 0x0000000000403b46 in generateInvertIDForAllPFAndC () at InvertIndexGen.cpp:254
#16 0x0000000000403d0b in main (argc=1, argv=0x7fffffffe448) at InvertIndexGen.cpp:47
(gdb)

At #14, InvertIndexGen.cpp:174, in meinem code oben, das ist, wo es abgestürzt:

map<int,int> M = mainMapIt->second; //THIS IS LINE 174.

Scheint es, dass, wenn ich rufe ->second, eine Kopie der jeweiligen Karte erstellt werden. Dies sollte der Grund sein, warum der St9bad_alloc als gut.

Aber in diesem Fall ist es etwas, was ich hier tun kann? Schließlich invertID.max_size() Gegenzug 18446744073709551615, und ich bin mit über 100 Millionen Schlüssel nur. Ich sehe es auch so aus top, dass mein Programm nutzt nur 10% des Speichers. (wir haben 128 GB RAM)

Was sind einige der Maßnahmen, die ich verwenden sollte, gegen diesen Fehler? Ich sehe einige meiner älteren Kollegen tun dies auch, und Sie berichten, dass, wenn Ihr umkehren index beginnt zu wachsen mehr als 70-80% des Speichers in top, das Programm startet, gehen drunter und drüber. Aber mein Programm nutzt nur 10%, also was ist hier Los? Was sind einige der Dinge, die wir tun können, um diesen Fehler zu vermeiden?

EDIT: einige Kommentare deuten darauf hin, mich zu prüfen, mit ulimit, so ist es hier:

-bash-3.2$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 1056768
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1056768
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
  • Sie sollten überprüfen, Ihre Verfahren begrenzt (start mit der globalen Grenzwerte mit der ulimit - Befehl). Der Speicher begrenzt werden einige Weg.
  • max_size ist ein rein theoretischer Wert und hat nichts zu tun mit den realen Arbeitsspeicher. Sollten Sie tiefer in Ihr memory-Nutzung, zu vergleichen, rss -, swap -, vsize des Prozesses, überprüfen Sie mögliche ulimits-und ist-Werte auf neu, und natürlich ist der Blick auf den Quellcode werfen die nicht verletzt auch.
  • Hier ist meine ulimit: -bash-3.2$ ulimit-a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 1056768 max locked memory (kbytes, -l), 32 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 10240
  • cpu time (seconds, -t) unlimited max user processes (-u) 1056768 virtual memory (kbytes, -v) unlimited file locks (-x) unbegrenzt
  • Ich habe aktualisiert die Frage mit ulimit
  • wenn Sie sagen, 100 Millionen Schlüssel,das ist von invertID? was ist der Wert jedes Elements (der submap) in invertID? wie groß ist das? 128gb, ist es sicher davon ausgehen, dann, dass Sie auf 64-bit-Maschine mit 64-bit-linux? wenn Sie mit top was bedeutet das virt sagen?
  • Ja, 100 Millionen Schlüssel ist für die invertID Karte allein. Für jede sub-Karte, die map<int,int> gibt es sehr wenige Tasten - es sollte etwa 1-20 Schlüssel. Die meisten der Zeit, ist es < 10. Nicht viel. Ich habe auch gezählt wird die Gesamtzahl einfügen eines neuen Schlüssel in jedes sub-Karte map<int,int> als gut, und durch die Zeit, stürzt es ab, ich habe invertID Größe 126,252,979 mit allen sub-Karten-Größe kombiniert: 1,319,366,634. Ja, das OS ist 64 bit, oder sonst, werden wir nicht in der Lage sein zu Programm ausführen, nimmt 80-90 GB auf unserem server.
  • es hängt davon ab. Wie halten wir nach dem einfügen des keys in die invert-index, virt hält auf der Erhöhung. virt, sagt 17.2 g für mein Programm vom letzten mal abgestürzt ist.
  • hmm, ich denke, es ist nicht der Arbeitsspeicher dann. ich Frage mich, ob Sie lief über die Erinnerung (wie das schreiben zu einem dangling pointer oder so etwas) woanders...
  • eine Sache, die Sie versuchen können, ist die Verwendung memtrack almostinfinite.com/memtrack.html. sehen Sie, wenn Sie geben Ihnen einen neuen Einblick...
  • und auch back-trace) in den stack und sehen, was der parameter in diesem Aufruf 0x00000034510bd1d9 in operator new(unsigned long) ()
  • In meinem Programm, ich benutze keine pointer-Variablen, die in der Verarbeitung Teil, also keine Referenzierung oder die Dereferenzierung von dort. Der einzige Teil, wo gibt es einige Hinweise, sind diejenigen, bei Iteratoren und c_str Funktion, wo ich brauche, const char*, für einige Funktionen. Aber es gibt keine Veränderung über Zeiger.

InformationsquelleAutor Karl | 2013-02-14
Schreibe einen Kommentar