Merkwürdiges "EXC_BAD_ACCESS"

  • Merkwürdiges "EXC_BAD_ACCESS"

    Hallo!

    Ich habe ein ziemlich merkwürdigen "EXC_BAD_ACCESS", dem ich nicht auf die Schliche komme. Ich gehe sehr davon aus, dass es sich um ein Memory-Management-Problem handelt, nur finde ich für das Debuggen keinen Ansatz, da der Fehler augenscheinlich in der Runloop erzeugt wird und ich im Debugger keine meiner eigenen Funktionen finde.

    Hier ein Screenshot (s. Anlage) des Debuggerfensters nach der Exception:

    Die App ist ein Server, der sich mit NSStream-Objekten arbeitet (die ich übrigens im Verdacht habe) und sich weitgehend am Beispiel des Online-Tic-Tac-Toe-Spiels aus dem Buch "More iPhone Development" orientiert. Der Absturz scheint aufzutreten, wenn ich das verbundene Gerät (iPhone) trenne bzw. die App beende.

    Wie kann ich hier am Besten weiter vorgehen? Ich habe meinen Code sorgfältig durchgesehen und entdecke keine Memory-Leaks. Auch der Analyzer spuckt nichts aus.

    Ich stecke fest und bin für jeden Tipp dankbar.
  • fwtag schrieb:

    :wacko: Vielen Dank - aber ich versteh kein Wort.

    Heap-Corruption: Du hast irgendwo in einen Speicherbereich geschrieben, in den Du nicht hättest schreiben sollen, aber durftest. Genaugenommen hast Du nicht in "freien" Speicher geschrieben, sondern in Speicher, der von irgendetwas anderem benutzt wird. Das führt dann viel später zu sehr komischen Dingen, weil der eigentliche Eigentümer (wie etwa eine Library) dort Daten vorfindet, die er nicht erwartet hat.

    Am besten findet man soetwas mit Valgrind. Das ist ein Programm, was wiederum Deine Anwendung startet, und jeden einzelnen Speicherzugriff überwacht. Ich weiss aber nicht, wie weit die Mac Version von Valgrind einsetzbar ist.

    Damit wir nicht neidisch auf MS Visual Studio blicken müssen, gibt es auch für den Mac eine praktische Funktion, die zumindest eingeschränkt hilft. Dafür muss man, bevor die Anwendung gestartet wird, ein paar Environment-Variablen setzen. Die führen dann dazu, dass malloc(), was in der Speicherzusicherung ganz unten und dicht am Kernel sitzt, den Speicher so anlegt, dass bspw. zwischen jeder Speicher-Seite eine leere Seite mit gesichert wird, welche aber geschützt ist. Da fliegt dann einem die Anwendung (hoffentlich) viel schneller um die Ohren, wenn man irgendwo "falsches" hinschreibt.
    Die notwendigen Variablen sind in den man-Pages zu malloc erklärt, interessant ist etwa MallocGuardEdges und MallocScribble. Je nach flags kann es aber passieren (so auch bei Valgrind), dass Deine Anwendung extrem langsam läuft. Das ist halt der Preis.

    Viel Erfolg!
    C++
  • fwtag schrieb:

    Danke, jetzt sehe ich klarer.
    Wenn Du es nicht findest, lass mal MiMo ran. Er ist sehr gut darin solche Fehler zu finden.
    Xcode 4 sucks – „,Multiple exclamation marks‘, he went on, shaking his head, are a sure sign of a diseased mind.‘“ (Terry Pratchett 1992: Eric)

    "Wir ordnen und befehlen hiermit allen Ernstes, dass die Advocati wollene schwarze Mäntel, welche bis unter das Knie gehen, unserer Verordnung gemäß zu tragen haben, damit man die Spitzbuben schon von weitem erkennt." (Friedrich Wilhelm I., Soldatenkönig)
  • Ich habe erst einmal mit Instruments -> ObjectAlloc experimentiert. Mir ist die Anwendung "halb" abgesemmelt, will sagen: Mein Menü ist eingefroren (Sat-1-Ball), aber die Kiste lebte noch soweit, dass der (Bonjour-)Service noch existent war, denn den habe ich erst beim Beenden der Applikation aus Instruments heraus verloren (das konnte ich im iPhone-Client durch mein relativ umfassendes Debug-Logging nachvollziehen).

    Interessant ist aber, dass, jedenfalls bei meinem Test-Szenario, ObjectAlloc einfach so weiter lief, als wäre nichts gewesen. Ich vermute, dass dieser Fehler eben im Rahmen des Runloops und/oder den entsprechenden CallBacks und/oder den angemeldeten Stream-Objekten passiert, also außerhalb "meines" Kontextes. Daher schlug ObjectAlloc nicht an.

    Hmm. 8|

    Ich werde mich mal mit der malloc-Geschichte, die Zerm vorgeschlagen hat, befassen. Denn mallocs finden durchaus statt, wenn man dem Beispiel aus dem genannten Buch folgt.

    Wer noch eine Idee hat ... ich würde mich freuen ;)
  • fwtag schrieb:


    Ich werde mich mal mit der malloc-Geschichte, die Zerm vorgeschlagen hat, befassen. Denn mallocs finden durchaus statt, wenn man dem Beispiel aus dem genannten Buch folgt.

    mallocs finden immer statt :P [obj alloc] ruft auch nur ganz tief unten irgendwann malloc(), wie auch der "new" Operator in C++.
    Ich denke, die Dev Tools, wie etwa ObjectAlloc etc. machen auch nicht viel anderes, als besagte Flags zu setzen. Das mit den Guard-Pages hatte ich aber noch nicht gesehen. Ansonsten, wie gesagt, Valgrind. Ich will auch ein Intel Mac, damit Valgrind auch bei mir läuft!
    C++
  • Ich brauch doch nochmal Eure Hilfe (bevor ich mich mit Valgrind auseinander setze ...):

    Ich habe in meiner App-Plist folgende Environment-Variablen gesetzt (s. Anhang). Die Werte kommen von der malloc-manpage, der plist-Eintrag heißt "LSEnvironment" und sollte eigentlich dafür sorgen, dass diese Variablen auch gesetzt werden. Nun ist es aber so, dass trotz dieser Variablen nichts passiert. Ich habe eben mit Mühe wieder den Absturz hinbekommen (fieses Stück!), aber keinerlei Infos bekommen, keinerlei frühere Abstürze, nichts. Alles so wie vorher, der Absturz erfolgt irgendwo in einer Callbackfunktion.

    Was mache ich falsch?

    # EDIT: *Hüstel* Anhang vergessen ...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von fwtag () aus folgendem Grund: Anhang vergessen ...

  • Hab da grad gelesen, dass es unter Xcode eine Option geben soll "Enable Guard Malloc" im Debug menü. Das scheint noch etwas einfacher und robuster zu sein.
    Das sollte dann im besten Fall dazu führen, dass Deine Anwendung dort crashed, wo der Fehler wirklich passiert, und nicht "irgendwann später vielleicht".
    C++
  • Ja, ich habe tatsächlich sofort einen hinter die Ohren bekommen, weil ich zwei Zeilen Code-Leiche hatte, die zu dem (einem?) Absturz führte. Ich erzähle lieber nicht, was das war ... Ich hoffe, dass das der Grund war. Mal sehen, ich werde jedenfalls noch weiter intensiv testen. Danke!!!

    Frage: Wenn ich folgende Informationen in der Debug-Console erhalte, dann lese ich das als reine Informationen und nicht als Hinweis, dass ich etwas falsch mache, oder?

    Quellcode

    1. GuardMalloc: Allocations will be placed on 16 byte boundaries.
    2. GuardMalloc: - Some buffer overruns may not be noticed.
    3. GuardMalloc: - Applications using vector instructions (e.g., SSE or Altivec) should work.
    4. GuardMalloc: GuardMalloc version 18
  • fwtag schrieb:

    Ja, ich habe tatsächlich sofort einen hinter die Ohren bekommen, weil ich zwei Zeilen Code-Leiche hatte, die zu dem (einem?) Absturz führte. Ich erzähle lieber nicht, was das war ... Ich hoffe, dass das der Grund war. Mal sehen, ich werde jedenfalls noch weiter intensiv testen. Danke!!!

    Frage: Wenn ich folgende Informationen in der Debug-Console erhalte, dann lese ich das als reine Informationen und nicht als Hinweis, dass ich etwas falsch mache, oder?

    Quellcode

    1. GuardMalloc: Allocations will be placed on 16 byte boundaries.
    2. GuardMalloc: - Some buffer overruns may not be noticed.
    3. GuardMalloc: - Applications using vector instructions (e.g., SSE or Altivec) should work.
    4. GuardMalloc: GuardMalloc version 18

    Glückwunsch!

    Ja, ist nur Information/Warnung. Steht nochmal genauer in der man-page erklärt: Weil 16-Byte-Aligned Speicher insbs. für SSE/AltiVec nötig ist, macht das auch der Malloc-Guard, um kompatibel zu sein. Deshalb ist es aber möglich, dass du bis zu 15 Bytes über die Grenzen schreiben kannst, ohne, das etwas passiert.
    C++