Debug:kein Fehler, Release:Fehler,Release(DebugInfo aktiv): kein Fehler



  • Hi Leute,
    ich hab ein Problem mit meinem Programm:

    Im Debug-Modus -> *kein Fehler
    Im Release-Modus -> *Fehlermeldung mit malloc (hab ihn mühselig im Code mit
    cout ausfindig gemacht)
    *keine Fehlermeldung mit new
    *Programmdatenbank aktivieren (also debuggen im Release-
    Modus): keine Fehlermeldung

    Weiteres Problem: Wenn ich im Release-Modus debugge, kann ich im Hauptprogramm Haltepunkte setzen, aber dann nicht in einen Aufruf springen (in andere Quellcodedatei, hab Pfade der include's gesetzt.

    Habt ihr ne Ahnung? Ist vielleicht malloc fehlerhaft???



  • ga_un schrieb:

    Hi Leute,
    ich hab ein Problem mit meinem Programm:

    Im Debug-Modus -> *kein Fehler
    Im Release-Modus -> *Fehlermeldung mit malloc (hab ihn mühselig im Code mit
    cout ausfindig gemacht)
    *keine Fehlermeldung mit new
    *Programmdatenbank aktivieren (also debuggen im Release-
    Modus): keine Fehlermeldung

    Weiteres Problem: Wenn ich im Release-Modus debugge, kann ich im Hauptprogramm Haltepunkte setzen, aber dann nicht in einen Aufruf springen (in andere Quellcodedatei, hab Pfade der include's gesetzt.

    Habt ihr ne Ahnung? Ist vielleicht malloc fehlerhaft???

    in den aufruf kannste evtl nicht springen, weil die funktion inline ist.
    kannste testhalber ja mal ausschalten, um besser debuggen zu können.
    der fehler liegt bestimmt nicht in malloc.
    es könnte unter umständen so gelaufen sein:

    char* a=malloc(10);
    a[-1]='x';
    char* b=malloc(10);
    

    das erste malloc hat sich speicher vom betriebssystem geholt, sagen wir mal 64k und den zerlegt in zwei portionen. nämlich 10 bytes für dich und den rest.
    na, eigentlich eher 18 bytes für dich , 8 bytes steuerinformation für den abgespaltenen kleinen block und 10 bytes nutzinhalt, den du kriegst. das macht man zum beispiel so, daß man, wenn 10 bytes anfordert, daß malloc in seiner liste such, obs irgendeinen block gibt, der größergleich als 18 bytes ist. jo, den mit 64 ka findet er. dann nimmt er die ersten 18 bytes und schreibt am anfang und am ende die zahl 18 rein. sieht dann so aus:
    |18|10 bytes|18|
    und den großen rerst behandelt er auch noch.
    |18|10 bytes|18|65510|65518 bytes|65518|
    wenn diese daten so rumliegen, können malloc und free damit allerhand anfangen.
    du hast als ergebnis von malloc die anfangsadresse der 10 bytes gekriegt.
    a) man kann von vorn bis hinten oder von hinten bis vorn durch die liste gehen. man weiß ja immer, wo der nächste block beginnt. einfach soweit springen, wie die zahl da sagt.
    b) man kann prima freigegebene blöcke mit nachbarn verschmelzen.
    nimm an, du rufst wieder free auf mit zeiger auf die 10 bytes. free geht 4 bytes zurück und findet da ne 18 stehen. dann geht free 18 bytes vor und sieht nen anderen block, der 65518 bytes groß ist. ups, hab vergessen, daß malloc/free sich auch merken sollten, ob ein block belegt ist. mal angenommen, das haben sie. free sieht, daß der nachbarblock auch frei ist und verschmilz die beiden. es entsteht:
    |65536|65518 bytes|65536|
    und free schaut sich natürlich auch gleich den nachbarblock an, ob der auch frei ist... und so weiter...

    aber oh weh! was passiert denn, wenn du schelm in den speicher müll reinschreibst?

    als die welt noch ok war...
    |18|10 bytes|18|65510|65518 bytes|65518|
    und du gemacht hast
    a[-1]='x'
    da entstand
    |120|10 bytes|18|65510|65518 bytes|65518|
    naja, dann viel spaß. wenn free hier versucht, was freizugeben, dann crasht es aber.
    auch malloc könnte versuchen, durch die liste zu gehen und wegen der 120 dort echt ins nirwana rennen.

    und die moral von der geschicht: malloc ist es nicht.
    die schuld liegt bestimmt in ner indexgrenzenüberschreitung irgendwo in deinem programm. und damit meine ich wirklich "irgendwo". hier ist debuggen jetzt leider glückssache und unerquicklick.



  • Hallo,

    danke für die Message.
    Kann es auch sein, das im Default-Konstruktor eines bestimmten Objekts, das ich benutze, eine Variable nicht initialisiert worden ist?

    ciao



  • ga_un schrieb:

    Hallo,
    danke für die Message.
    Kann es auch sein, das im Default-Konstruktor eines bestimmten Objekts, das ich benutze, eine Variable nicht initialisiert worden ist?
    ciao

    ja.
    im debugmodus wied sie auf 0xcdcdcdcd gesetzt, im releasemodus bleibt sie uninitialisiert.
    ist das objekt ein auto-objekt, wird der wert davon abhängen, was vorher gemacht wurde. kann gemein sein.

    int arr[1];
    arr[1]=4711;
    {for(int i=0;i<100;++i)
    {
    }}
    int a;
    cout<<a<<endl;
    

    gibt im debug-mode cirka -850000000 aus. (0xcdcdcdcd).
    im releasmode ohne optimierung vermutlich 100, mämlich den alten wert von i. der speicher, den damals i ainnahm, nimmt jetzt a ein.
    mit optimierung vermutlich 4711, nämlich arr[1] (liegt ja außerhalb des indexbereichs);. die ganze schleife mit i wurde wegoptimiert.

    bei dickeren sachen kann es auch nen unterschied machen, wieviele debug-informationen in die exe reingelinkt worden sind.

    weiterhin viel glück bei der suche.



  • Hallo,

    kann mich die Fehlersuche mit cout bzw. MessageBox auch in die Irre führen? Irgendwie kommt die Fehlermeldung im Release-Modus beim überladenen operator= Datentyp string.

    class Klasse
    {
    private:
    string m_sString;
    int    m_iWert;
    public:
    Klasse();
    ~Klasse();
    Klasse& operator=(Klasse &a_cKlasse);
    };
    //...
    Klasse&
    Klasse::operator=(Klasse &a_cKlasse){
     m_iWert   = a_cKlasse.m_iWert;
     m_sString = a_cKlasse.m_sString; // Fehlermeldung an dieser Stelle: Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden
    }
    

    Liegt es jetzt an m_sString (m_sString.assign(a_cKlasse.m_sString): gleicher Fehler) oder doch mit nicht korrekt freigegebenen Ressourcen???



  • ga_un schrieb:

    Hallo,
    kann mich die Fehlersuche mit cout bzw. MessageBox auch in die Irre führen? Irgendwie kommt die Fehlermeldung im Release-Modus beim überladenen operator= Datentyp string.

    fehler in der stringausgabe hab ich am häufiogsten gesehen, wenn das den string enthaltende objekt NULL war.

    Klasse& Klasse::operator=(Klasse &a_cKlasse){
     cout<<"ausgabestring liegt an adresse "<<&a_cKlasse<<endl;
     m_iWert   = a_cKlasse.m_iWert;
     m_sString = a_cKlasse.m_sString; // Fehlermeldung an dieser Stelle: Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden
    }
    


  • Hallo,
    meine main sieht ungefähr so aus!
    Mit malloc kommt im Release-Modus die Fehlermeldung,
    mit new nicht?!

    int main()
    {
    	Klasse* t_cTest1=(Klasse*)malloc(sizeof(Klasse)*20);
    	Klasse* t_cTest=(Klasse*)malloc(sizeof(Klasse)*20);
    	//Klasse* t_cTest1 = new Klasse[20];
    	//Klasse* t_cTest = new Klasse[20];
    
    	for(int i=0;i<20;++i){
    		t_cTest1[i]= t_cTest[i]; // springt in operator= -> Fehlermeldung
    	}
    	if(t_cTest1){
    		free(t_cTest1);
    		//delete [] t_cTest1;
    		t_cTest1 = NULL;
    	}
    	if(t_cTest){
    		free(t_cTest);
    		//delete [] t_cTest;
    		t_cTest = NULL;
    	}
    
    	return 0;
    }
    


  • Im Forum C++ hab ich so ein ähnliches Programm geschrieben.
    Mit new/delete wird neben Speicherplatzreservierung der Konstruktor aufgerufen, mit malloc wird nur Speicherplatz reserviert.

    malloc sollte wohl in C++ für Objekte nicht verwendet werden, oder??



  • ga_un schrieb:

    Im Forum C++ hab ich so ein ähnliches Programm geschrieben.
    Mit new/delete wird neben Speicherplatzreservierung der Konstruktor aufgerufen, mit malloc wird nur Speicherplatz reserviert.
    malloc sollte wohl in C++ für Objekte nicht verwendet werden, oder??

    korrekt.
    ich hab angenommen, du verwendest malloc nur da, wo man es verwenden darf, und es sei ein schwer zu findender fehler.
    wenn du einfach konstruktoren nicht aufgerufen hast, isses klar. deine main() hat ganz klar den fehler, daß konstruktoren nicht aufgerufen werden.


Anmelden zum Antworten