Speicherzugriffsfehler (Speicherabzug geschrieben)



  • Hallo,

    Ich bräuchte kurz Hilfe zu meinem Code.
    Vorab: Es handelt sich um Code, der mit BALL und C++ programmiert wurde.
    An einer Stelle im Code erhalte ich einen Speicherzugriffsfehler. Ich nehme mal an, dass meine Variable nicht genug Speicherplatz bietet.
    Habe auch schon im Internet gesucht, aber nichts gefunden, das mir helfen konnte.
    Ich gebe erstmal nur die beiden Methoden an, um die es geht, da ich denke, der Fehler müsste dort zu finden sein.

    //Zählen der Kontakte zwischen den Aminosäuren
    int countContacts(Atom* atom, Protein* protein)
    {
            int contacts = 0;
    	for (ChainIterator ch_it = protein->beginChain(); +ch_it; ++ch_it)
    	{
    		for (ResidueIterator r_it = ch_it->beginResidue(); +r_it; ++r_it)
    		{
    			if (r_it->isAminoAcid()) 
    			{
    				// Berechnung des Abstandes zwischen den C-alpha Atomen von zwei Aminosäuren
    				// und zählen der Kontakte, wenn der Abstand <= 7 ist
    				Atom* atom1 = r_it->getAtom("CA");
                    int dist = atom->getPosition().getDistance(atom1->getPosition());
    
                    if (dist <= 7) 
                    {
    					contacts += 1;
                    }
                 }
    		}
    	}
    	return contacts;
    }
    
    // Zählen der Kontakte und Bestimmung der Häufigkeitsmatrix
    void getHaeufigkeitsMatrix(Protein* protein)
    {
    	for (ChainIterator ch_it = protein->beginChain(); +ch_it; ++ch_it)
    	{
    		for (ResidueIterator r_it = ch_it->beginResidue(); +r_it; ++r_it)
    		{
    			if (r_it->isAminoAcid()) 
    			{
                    // HIER bei int k ERHALTE ICH DEN SPEICHERZUGRIFFSFEHLER
                    int k = countContacts(r_it->getAtom("CA"), protein) - 1; // -1, weil auch Kontakt mit sich selbst berechnet wird
                    String a = Peptides::OneLetterCode(r_it->getName());
                    // hier soll dann die Matrix gefuellt werden
    			}
    		}
    
    	}
    }
    

    Ich habe dazugeschrieben, an welcher Stelle ich den Fehler erhalte.
    Wenn ihr noch Infos benötigt, sagt bescheid.
    Da man zur Ausführung des Programms einen Ordner mit über 100 Dateien benötigt, über die iteriert wird, ist es auch schwierig, dass ihr den Code testen könnt.
    Aber vielleicht sieht jemand auf Anhieb das Problem.

    Schon mal Danke.



  • r_it wird vermutlich ungültig sein.



  • Nein, das kann es nicht sein.
    Ich kann k auf der Konsole ausgeben lassen.
    Die Methode countContacts gibt eine Anzahl Kontakte zurück, also ein int.
    Zu jeder Aminosäure wird solch ein Kontakt berechnet.
    Nur ab einem gewissen Punkt bricht er ab mit dem Fehler "Speicherzugriffsfehler(Speicherabzug geschrieben".



  • Verwende doch mal den Debugger und schaue, ob einer von den Pointern NULL ist.



  • Hab den Debugger verwendet.
    Folgendes gibt er mir aus:

    Program received signal SIGSEGV, Segmentation fault.
    0x00007ffff36da614 in BALL::TVector3<float>::getDistance(BALL::TVector3<float> const&) const () from /usr/lib/libBALL.so.1.4
    


  • Nein, du sollst mit dem Debugger in die Funktion gehen und dir dort die Werte der Pointer anzeigen lassen.
    Was ist das überhaupt für eine komische Abbruchbedingung in den for-Schleifen?



  • Ich weiß grad nicht, wie ich mit dem Debugger in die Funktion gehe. Habs mit gdb probiert laut Anleitung, die ich im Internet gefunden hab, aber das klappt irgendwie nicht.

    Welche Abbruchbedingung meinst du? Das meiste sind Funktionen aus BALL (http://ball-trac.bioinf.uni-sb.de/wiki/CodeLibrary).


  • Mod

    AlienFan schrieb:

    Welche Abbruchbedingung meinst du?

    Alle deine Abbruchbedingungen. Was die Abbruchbedingung einer for-Schleife ist, weißt du? Alle deine For-Schleifen sehen aber so oder ähnlich aus:

    for (ChainIterator ch_it = protein->beginChain(); +ch_it; ++ch_it)
    

    +ch_it? Das sieht mir doch sehr nach einem Schreibfehler aus. Vielleicht ist *ch_it gemeint?



  • Ja sicher weiß ich, was eine Abbruchbedingung ist.
    Die sind aber korrekt so.
    Auf der Webseite von BALL steht folgendes bei einem Beispiel:

    Note that +ch_it equals ch_it != protein->endChain()
    

    Ich hab noch gesagt bekommen, dass es sein kann, dass es das CA-Atom (welches ich abfrage), nicht existiert.
    Ich habe dann in der countContacts abgefragt, ob atom oder atom1 nicht NULL sind:

    //Zählen der Kontakte zwischen den Aminosäuren
    int countContacts(Atom* atom, Protein* protein)
    {
            int contacts = 0;
        for (ChainIterator ch_it = protein->beginChain(); +ch_it; ++ch_it)
        {
            for (ResidueIterator r_it = ch_it->beginResidue(); +r_it; ++r_it)
            {
                if (r_it->isAminoAcid())
                {
                    // Berechnung des Abstandes zwischen den C-alpha Atomen von zwei Aminosäuren
                    // und zählen der Kontakte, wenn der Abstand <= 7 ist
                    Atom* atom1 = r_it->getAtom("CA");
                    if (atom || atom1 != NULL)
    		      {
                      int dist = atom->getPosition().getDistance(atom1->getPosition());
    					if (dist <= 7) 
    					{
    						contacts += 1;
    					}
    				}
                 }
            }
        }
        return contacts;
    }
    

    Aber das hat keine Änderung gebracht.



  • warum probierst du nicht, was SeppJ vorgeschlagen hat? +ch_it ist womöglich Schreibfehler für *ch_it, und dann kannst du auch gleich prüfen, ob +r_it ein SChreibfehler für *r_it ist.



  • Er schreibt ja, dass die Bibliotheksentwickler eine äusserst kreative Operatorüberladung einsetzen. Manchmal sind benannte Funktionen (oder schlicht der Vergleich mit end) echt besser...



  • Ich würde den Code auf ch_it != protein->endChain() ändern. Also weder +ch_it noch *ch_it .

    Um sicherzugehen dass die Doku nicht einfach falsch ist. Weil das unäre "+" zu überladen ja echt seltsam ist. Und wenn die Doku doch korrekt ist muss es ja egal sein.
    Und allein schon wegen dem "principle of least surprise" würde ich da lieber ch_it != protein->endChain() stehen haben als +ch_it .

    @AlienFan
    Das ist eine gute Möglichkeit für dich dich mit einem interaktiven Debugger auseinanderzusetzen. Mit einer IDE wie Netbeans, Codeblocks oder Eclipse CDT kann man damit echt schön arbeiten.
    Die ersten Schritte mit solchen Tools sind immer ein wenig mühsam und zeitraubend, aber je früher du dich damit vertraut machst, desto mehr Zeit sparst du dir später beim Fehlersuchen.
    Man kann solche Bugs natürlich auch ohne Debugger finden, aber mit geht es meist um Grössenordnungen schneller.


Anmelden zum Antworten