Wie St9bad_alloc beseitigen?



  • Hallo,

    ich kann leider kein Minimalbeispiel posten weil mein code etwas größer ist. Mir geht es vielmehr darum zu erfahren wie ihr mit St9bad_allocs umgeht bzw. wie ihr versucht diese zu beseitigen. Mein code läuft leckfrei und auch korrekt (nach validierungen). Bei einem bestimmten input der von der Größe eigentlich nur ca. 100 MB braucht fängt mein Programm die bad_alloc exception ab. Mittels valgrind bekomme ich nur die message dass in einer bibliotheksfunktion an die ich arrays übergebe die aus den input daten bestehen ein

    Use of uninitialised value of size 4
    ==10905==    at 0x46C23D8: (within /usr/lib/atlas/sse2/libblas.so.3.0)
    Warning: silly arg (-1248597728) to __builtin_vec_new()
    **10905** new/new[] failed and should throw an exception, but Valgrind
       cannot throw exceptions and so is aborting instead.  Sorry.
    ==10905==    at 0x4021841: VALGRIND_PRINTF_BACKTRACE (valgrind.h:2366)
    ==10905==    by 0x4021A89: operator new[](unsigned) (vg_replace_malloc.c:195)
    ==10905==    by 0x8057587: //hier kommt der trace meines codes
    

    . Ich weiß leider nicht wie ich sinnvollerweise an die sache rangehen soll da ich glaube dass der fehler bei mir liegt. Ich habe einen referenzcode der auch diese bibliothekfunktion verwendet und da krachts nicht.

    Wie würdet ihr vorgehen?

    Danke



  • Geh doch mit dem Debugger schrittweise durch und schaue, wie Speicher angefordert wird bzw. ob die Variablen korrekt sind.



  • [Vermutung]

    Du versuchst zu viel Speicher anzufordern.
    Guck dir die Stelle wo die Exception fliegt nochmal genau an.

    Du versuchst da ein Array anzufordern, das garnicht in den Speicher passt. -> Überlauf -> Fehler.

    [/Vermutung]



  • Die Warnung in Zeile 3 sieht nett aus - __builtin_vec_new klingt entfernt nach etwas in Richtung new[], und da ein Argument von -1248597728 ist seltsam oder?
    Uninitialisierter Wert oder Wert nach Überlauf an new[] übergeben?



  • Ich frage mich sowieso, wie dort ein negativer Wert zustande kommen kann, da man bei Speicheranforderungen immer mit unsigned -Typen arbeitet. Da muss fast was Grösseres schief gelaufen sein... Oder es passiert einfach etwas Willkürliches.

    fragerzeichen, lass das Programm mit Debugger, aber ohne ohne Valgrind laufen, und verfolge die std::bad_alloc -Exception über den Stackframe bis zur Entstehungsstelle zurück.



  • @Nexus: kann leicht sein dass nur die Ausgabe signed ist.

    Ist aber auch ziemlich egal, da die mir bekannten Systeme sowieso keine zusammenhängenden Speicherbereiche unterstützen, deren Grösse jemals das höchstwertige Bit gesetzt haben könnte.

    Ob man den "Sanity-Check" dann als if (size & high_bit_mask) oder als if (size < 0) implementiert, ist im Grunde genommen egal. Ersteres ist natürlich "schöner" und "sauberer". Aber tun werden beide dasselbe.



  • Hmm....also ich debugge gerade und lege eine Array der Größe an:

    my_array = new T[len_j * len_i];
    

    Der debugger sagt len_j = 19514 und len_i = 19514.
    Der Template Typ ist double. Damit lege ich ja
    19514*19514*8 = 3046369568 Byte = 2905.24 MByte = 2.837 GByte an oder?
    Ist die Rechnung korrekt?

    Das würde meine 2 GB Speicher sprengen und damit würde die Badalloc exception korrekt sein....



  • Das kann gut sein, ja.



  • Es kann auch schon viel früher als bei deiner RAM-Grösse zu einer std::bad_alloc kommen, zum Beispiel, wenn kein so grosser zusammenhängender Block gefunden werden kann. Und ein 2.8GB-Block ist riesig. Andererseits kann die Auslagerungsdatei unter Umständen dafür sorgen, dass mehr Speicher angefordert werden kann (der Computer wird dann langsam), wahrscheinlich aber eher bei kleineren Blöcken.

    Deinen Speicherverbrauch kannst du bestimmt stark reduzieren, dazu müsstest du allerdings etwas konkreter werden.



  • Deinen Speicherverbrauch kannst du bestimmt stark reduzieren, dazu müsstest du allerdings etwas konkreter werden.

    Ich baue intern aus einer systemmatrix eine submatrix auf die für diesen einen speziellen fall ca. 400 Millionen Einträge hat. Anderer input der sogar größer ist aber dafür dünner produziert den bad alloc nicht. Es ist also durchaus input-speichergrößen-abhängig und auch die referenzimplementierung bricht da zusammen.

    Dennoch: Ich freue mich dazu gebracht worden zu sein nochmals die subalgorithmen durchzudenken.
    Danke an dieser stelle für den Austausch!


Anmelden zum Antworten