SOLVED: Brauche einen Rat beim Debuggen...



  • Wutz schrieb:

    Lass dir nicht alles einzeln aus der Nase ziehen,
    gib die Definition von N und aller beteiligten Typen konkret an (ohne Abschreib-Fehler).

    Hab den Code ergänzt.



  • Hast du bei malloc/realloc auch immer das richtige sizeof benutzt?

    Nutze den dereferenzierten Zeiger für sizeof

    int *p;
    
    p = malloc(1000*sizeof(int))   // schlecht, da du wissen muss, was p ist.
    p = malloc(1000*sizeof(*p))    // besser 
    p = malloc(1000*sizeof(p[0]))  // geht auch
    

    Gerade bei deinen vielen structs besteht leicht die Möglichkeit, dass du das bei copy&paste mal vergessen hast.

    Dein N oder M kann ja schon von der Größe falsch sein.
    Hat sich evtl. schon M oder pNode oder Gamma verändert (irgendein Zeger auf dem Weg zu Gamma[3]?
    Hat Gamma überhaupt min. 4 Elemente?

    Benutzt du VLA oder Rekursion (reicht dein Stack)?



  • int SubdivideOneFBox(FBBox* FB, TMesh* M){
    

    - Definition von TMesh fehlt

    M zeigt ja wohl irgendwie auf FB, wenn du also durch realloc den FB-Speicherbereich verschiebst (und die Größe änderst), wie stellst du dann sicher, dass M davon was mitbekommt?
    Ich sehe auch kein free zu deinem realloc.



  • Gast3 schrieb:

    3. du solltest zur besseren Fehlereingrenzung von deinem C#-GUI wegkommen und direkt den C/C++ Code Debuggen - also einfach die DllMain durch eine echte/hartkodierte main mit deinem Test ersetzen- und die Dll als Executable kompilieren - dann hast du garantiert keine Debugging-Probleme mehr - ausserdem ist C# für die Fehlereingrenzung nicht relevant und stört nur - oder ist der Auslöser (aber das merkst du dann sehr schnell)

    Langfristig, gerne. Aber ich habe mich mit QT noch nicht auseinandergesetzt und das Programm ist schon sehr weit fortgeschritten:
    https://www.youtube.com/watch?v=iCjezalOBP4

    Muss das jetzt so erstmal fertig bringen...
    Außerdem wurde mir hier im Forum gesagt: "Nutze nie C/C++ um GUIs zu
    programmieren!!" 😋

    das meinte ich nicht - du sollst nur für die Fehlereingrenzung das GUI Verlassen und die Dll (kurz mal) in eine Applikation umwandeln und dort deinen Test machen - dann wäre klar ob es an C# oder C/C++ liegt (es ist für niemanden hier klar wie C# die Schnittstelle nutzt), und dein Debugger funktioniert anständig



  • Gast3 schrieb:

    5. Aufräumen und solche ausgeschriebenen Vorkommen von "FB->FBox[i]..." durch lokale Referenz/Pointer ersetzen - schon zu oft ein falsches Einstechen bei so
    [x][y][z] Einstech-Orgien gesehen

    for (i = 0; i < 8/*Magic Value*/; i++)
    { 
      /*auto&*/ curr_fbox = FB->FBox[i];
      /*auto&*/ n_359_gamma3 = N[359].Gamma[3]; // falls wirklich wie eine Art Konstante genutzt
     
      printf("n_359_gamma3 = %2.4e\n", n_359_gamma3); /*Liefert 0.2500e000*/ 
      curr_fbox.F_Thread = (TFace**)realloc(curr_fbox.F_Thread, curr_fbox.npFace * sizeof(TFace*)); /*Hier wird der Wert überschrieben*/ 
      printf("n_359_gamma3 = %2.4e\n", n_359_gamma3); /*Liefert 9.12e-008*/ 
      if (curr_fbox.F_Thread == NULL){ printf("ERROR - Unable to allocate memory!\n"); getchar(); return 1; } 
      curr_fbox.npFace = 0;
      ...
    }
    

    Schwierig, denn genau darin liegt die Systematik, wenn ich eine Menge in genau acht Untermengen räumlich unterteilen möchte. Außerdem funktioniert die Routine so. Ich habe sie häufig eingesetzt und sie hat stets das richtige geliefert.

    du sollst ja auch nur aufräumen - nicht die Semantik verändern

    1. hättest du dann eher das fehlende break gesehen und 2. passieren dann Indizierungsfehler viel seltener



  • noch ein Tip:

    das Fehler-Szenario so schnell wie möglich reduzieren

    -bleib in C/C++ mit deinen Tests - lass C# erstmal raus

    -mind 2. Testszenarien hart im Code - ein funktionierendes 1 falsches
    z.B. nur in der Dll eine Textdatei oder sonstige Datengrundlage laden und durchjagen - Fehler reproduzieren

    ich würde mir z.B. einfach eine init oder sonstige Routine in der Dll suchen und dort hart eine test_fehler() routinen einbauen die mir die Daten laed und die SubdivideOneFBox aufruft, wenn der dort nicht auftritt liegt der Fehler einfach irgendwo anders

    schnell und einfach



  • Wutz schrieb:

    int SubdivideOneFBox(FBBox* FB, TMesh* M){
    

    - Definition von TMesh fehlt

    M zeigt ja wohl irgendwie auf FB, wenn du also durch realloc den FB-Speicherbereich verschiebst (und die Größe änderst), wie stellst du dann sicher, dass M davon was mitbekommt?
    Ich sehe auch kein free zu deinem realloc.

    Nein, M zeigt nicht auf FB. M beinhaltet alle Knoten, Flächen und Zelle. Ich übergebe es nur um den Wert von N[359].Gamma[3] überwachen zu können.
    Die Funktion an sich würde ohne das Argument TMesh* M funktionieren.

    Ein free gibt es erst, wenn das Programm beendet wird, oder das Gitter aus dem Speicher gelöscht wird. Die Daten sollen im Speicher bleiben. Das ist der Sinn, dass die Daten am Anfang einmal berechnet werden und dann im Laufe weiterer Berechnungen zur Verfügung stehen.

    typedef struct TMesh{
    	char* Name;
    	char* FileName;
    	char* FullFileName;
    	char* PathName;
    
    	unsigned int Index;
    	unsigned int Dimension;
    
    	struct TNode* pNode;
    	struct TEdge* pEdge;
    	struct TFace* pFace;
    	struct TCell* pCell;
    	struct TFamily** ppFamily;
    
    	unsigned long nNode, MinNodeIndex;
    	unsigned long nEdge, MinEdgeIndex;
    	unsigned long nFace, MinFaceIndex;
    	unsigned long nCell, MinCellIndex;
    	unsigned int npFamily;
    
    	struct TNode** ppExternalNode;
    	unsigned long nExternalNode;
    
    	struct TCell** ppExternalCell;
    	unsigned long nExternalCell;
    
    	double MinEdgeLength;
    	double MaxEdgeLength;
    
    	struct TVariable* pVariable;
    	unsigned int nVarialbe;
    
    	struct NBBox NBox;
    }TMesh;
    
    extern __declspec(dllexport) void ChangeMeshName(char* Name, TMesh* M){
    	if (Name != NULL){
    		M->Name = (char*)realloc(M->Name, (strlen(Name) + 1) * sizeof(char));
    		strcpy(M->Name, Name);
    	}
    }
    


  • Gast3 schrieb:

    Gast3 schrieb:

    3. du solltest zur besseren Fehlereingrenzung von deinem C#-GUI wegkommen und direkt den C/C++ Code Debuggen - also einfach die DllMain durch eine echte/hartkodierte main mit deinem Test ersetzen- und die Dll als Executable kompilieren - dann hast du garantiert keine Debugging-Probleme mehr - ausserdem ist C# für die Fehlereingrenzung nicht relevant und stört nur - oder ist der Auslöser (aber das merkst du dann sehr schnell)

    Langfristig, gerne. Aber ich habe mich mit QT noch nicht auseinandergesetzt und das Programm ist schon sehr weit fortgeschritten:
    https://www.youtube.com/watch?v=iCjezalOBP4

    Muss das jetzt so erstmal fertig bringen...
    Außerdem wurde mir hier im Forum gesagt: "Nutze nie C/C++ um GUIs zu
    programmieren!!" 😋

    das meinte ich nicht - du sollst nur für die Fehlereingrenzung das GUI Verlassen und die Dll (kurz mal) in eine Applikation umwandeln und dort deinen Test machen - dann wäre klar ob es an C# oder C/C++ liegt (es ist für niemanden hier klar wie C# die Schnittstelle nutzt), und dein Debugger funktioniert anständig

    Achso. Ich habe bei der Ausführung der DLL eine Konsolenausgabe definiert. Aber ich kann das auch mal versuchen. Dauert nur ein wenig, denn so einfach ist das nicht, alle Usereingaben fest zu schreiben.



  • Gast3 schrieb:

    noch ein Tip:

    das Fehler-Szenario so schnell wie möglich reduzieren

    -bleib in C/C++ mit deinen Tests - lass C# erstmal raus

    -mind 2. Testszenarien hart im Code - ein funktionierendes 1 falsches
    z.B. nur in der Dll eine Textdatei oder sonstige Datengrundlage laden und durchjagen - Fehler reproduzieren

    ich würde mir z.B. einfach eine init oder sonstige Routine in der Dll suchen und dort hart eine test_fehler() routinen einbauen die mir die Daten laed und die SubdivideOneFBox aufruft, wenn der dort nicht auftritt liegt der Fehler einfach irgendwo anders

    schnell und einfach

    Also, ich werde das tun. Aber während die DLL arbeitet, ruht ja der Code in C#. Und in der DLL wird der korrekte Wert berechnet und später überschrieben. Das geschieht ja alles, während C# ruht. Aber ich werde das mal versuchen umzuschreiben - ist auch zum Teil schon im Code vorgesehen, einfach auch, dass ich es evtl. online stellen kann.



  • @Gast3: Ich habe die DLL jetzt als Executable kompiliert und lade die gleiche Datei ein. Der Fehler tritt aber unabhängig davon auf - wieder bei einem realloc-Befehl.

    Was kann dazu führen, dass realloc diesen Speicher überschreibt?

    Kann es helfen, wenn ich das komplette Projekt inkl. der Datei, die gelesen wir, mal online stelle?



  • CJens schrieb:

    Was kann dazu führen, dass realloc diesen Speicher überschreibt?

    Das
    - der Speicher vorher nicht für dich reserviert war.
    - dein Zeiger auf nicht mehr gültigen Speicher zeigt, weil du nicht alle Kopien des Zeigers (nach einem realloc) ersetzt hast.



  • DirkB schrieb:

    CJens schrieb:

    Was kann dazu führen, dass realloc diesen Speicher überschreibt?

    Das
    - der Speicher vorher nicht für dich reserviert war.
    - dein Zeiger auf nicht mehr gültigen Speicher zeigt, weil du nicht alle Kopien des Zeigers (nach einem realloc) ersetzt hast.

    Das kann ich eigentlich ausschließen, da ich den Speicher erst wenige Zeilen vorher reserviere und überprüfe. Außerdem dürfte die Funktion dann nicht den korrekten Wert liefern. Kann es daran liegen, dass ich weit vorher irgendwo über einen Index hinaus gelaufen bin?



  • Also, jetzt wirds etwas ekelhaft, aber vielleicht hilft das. Ich habe ja den Code der DLL so abgeändert, dass ich ihn auch als Executable ausführen kann.

    Wenn ich das Projekt in VS 2015 kompiliere, tritt der Fehler auf.
    Kompiliere ich es in VS2013, tritt der Fehler NICHT auf.



  • Wenn ich das Projekt in VS 2015 kompiliere, tritt der Fehler auf.
    Kompiliere ich es in VS2013, tritt der Fehler NICHT auf.

    ich denke nicht das du einen Fehler in VStudio entdeckt hast sondern eher irgendein undefined-behavior oder sonstiges anstoesst - sowas merkt man oft bei Kompilerwechsel

    Kann es helfen, wenn ich das komplette Projekt inkl. der Datei, die gelesen wir, mal online stelle?

    wenn du es kannst/darfst - hilft es bestimmt mehr als es nicht zu tun



  • Gast3 schrieb:

    Wenn ich das Projekt in VS 2015 kompiliere, tritt der Fehler auf.
    Kompiliere ich es in VS2013, tritt der Fehler NICHT auf.

    ich denke nicht das du einen Fehler in VStudio entdeckt hast sondern eher irgendein undefined-behavior oder sonstiges anstoesst - sowas merkt man oft bei Kompilerwechsel

    Kann es helfen, wenn ich das komplette Projekt inkl. der Datei, die gelesen wir, mal online stelle?

    wenn du es kannst/darfst - hilft es bestimmt mehr als es nicht zu tun

    Also, weil hier andere User (nicht Du) gerne mal empfindlich reagieren: Mir ist klar, dass ich keinen Compilerfehler entdeckt habe. VS2013 wird genau so korrekt arbeiten wie VS2015 - aber ich muss das ja hier posten, wenn ich es entdecke. Kann es an Einstellungen liegen? Kann ich den Compiler vielleicht noch etwas kleinlicher einstellen, dass er bei geringeren Fehler schon anspricht oder so? Optimierung ist in beiden Fällen deaktiviert - aber das wird ja glaube ich im Projekt gespeichert.

    Ich habe hier nur sehr langsames Handy Internet, aber ich werde in etwa einer Stunde mal das Projekt hochladen UND ein Video auf Youtube stellen, welches den Fehler zeigt.

    realloc überschreibt übrigens keinen verwendeten Speicher. N[359].Gamma[3] ist im aktuellen Fall in Adresse 3 987 192 gespeichert.
    Der Speicher, welcher reserviert wird (bei npFace = 1) ist 3 987 248 - ist nur ein Feld, variiert natürlich bei jedem Ausführen.



  • Gibt es Fehlermeldungen beim Kompilieren?

    Könnten (fehlerhafte) Fließkommaberechnungen den Fehler mitverursachen?

    Gibt es schon eine Fehlertheorie(n) (verfehltes Speichermanagement, verdächtige Zeiger o.ä) ?

    Wie sieht das Testszenario aus?

    Was sagt die Fehlerdatenbank?

    Breakpoints kann man zur Not auch von Hand setzen. Besser sind aber Fehlersuchtools für bestimmte Aufgaben.

    Wie zeigt sich der Bug, bzw. wie hast du den Fehler überhaupt selbst entdeckt?
    Eventuell gibt es keinen Fehler, alles nur ein Irrtum?

    Gibt es irgendwo (verdächtige) Zeitverzögerungen (Profiler o.ä.) ?

    Eine stärkere Modulstruktur ist generell debuggingfreundlicher.

    Guidelines kennen hilft ebenfalls z.B.:
    http://www.informit.com/articles/article.aspx?p=1823696&seqNum=2
    http://stackoverflow.com/questions/21006707/proper-usage-of-realloc
    Außerdem lassen sich solche Guidelines/Guides gut automatisieren bzw. automatisiert testen.



  • nachtfeuer schrieb:

    Gibt es Fehlermeldungen beim Kompilieren?

    Nein, gibt keine.

    nachtfeuer schrieb:

    Könnten (fehlerhafte) Fließkommaberechnungen den Fehler mitverursachen?

    Das glaube ich nicht. Ich lese mehrere tausend Zahlen ein - und ich gebe mir das Ergebnis anschließend aus. Die Koordinaten sind alle korrekt, sonst würde die 3D Darstellung des Gitters das zeigen.

    nachtfeuer schrieb:

    Gibt es schon eine Fehlertheorie(n) (verfehltes Speichermanagement, verdächtige Zeiger o.ä) ?

    Ich denke, dass ich irgendwann beim Einlesen mit einem Zeigerindex über ein Feld hinaus fahre und dabei irgend etwas überschreibe, was mir später diesen Fehler verursacht. Ich habe eben mal alle Koordinaten die gelesen werden in MS Excel geladen, das Zahlenformat auf acht Nachkommastellen gesetzt, die Daten in der Datei ersetzt, dann trat exakt der gleiche Fehler etwas später in genau der gleichen Routine auf.

    nachtfeuer schrieb:

    Wie sieht das Testszenario aus?

    Ich kann die Funktion, welche N[359].Gamma[3] erneut berechnet nach dem Einlesen nochmals manuell ausführen, dann Berechnungen starten. Ich kann die Poissongleichung auf dem Rechengitter lösen, das heißt, dass alles funktionieren muss. Es darf kein Wert falsch sein, sonst würde das Gleichungssystem nicht lösbar sein. Aber der Code stürzt manchmal unvorhergesehen ab.
    Ich arbeite seit acht Monaten täglich an dem Code - ich fühle mich einfach nicht wohl, wenn ich weiß, dass das auftritt. Bei anderen Gitterdateien tritt das scheinbar nicht auf.

    nachtfeuer schrieb:

    Breakpoints kann man zur Not auch von Hand setzen. Besser sind aber Fehlersuchtools für bestimmte Aufgaben.

    Jetzt wo ich die DLL als Executabel ausführe, kann ich auch Breakpoints setzen und tue das auch. Aber die zeigen mir nichts anderes. Vor dem Realloc ist der Wert korrekt, danach nicht mehr.

    nachtfeuer schrieb:

    Wie zeigt sich der Bug, bzw. wie hast du den Fehler überhaupt selbst entdeckt?
    Eventuell gibt es keinen Fehler, alles nur ein Irrtum?

    Ich habe den Fehler entdeckt, weil die Berechnungsergebnisse um diesen Punkt nicht korrekt dargestellt wurden.

    Gibt es irgendwo (verdächtige) Zeitverzögerungen (Profiler o.ä.) ?

    Eine stärkere Modulstruktur ist generell debuggingfreundlicher.

    Aber es ist wirklich auffällig, dass das gleiche Projekt mit VS2013 den Fehler nicht zeigt.



  • CJens schrieb:

    realloc überschreibt übrigens keinen verwendeten Speicher. N[359].Gamma[3] ist im aktuellen Fall in Adresse 3 987 192 gespeichert.
    Der Speicher, welcher reserviert wird (bei npFace = 1) ist 3 987 248 - ist nur ein Feld, variiert natürlich bei jedem Ausführen.

    Wie kommst du an die Adressen?

    Hast du schon den Debugheap von VS benutzt?



  • Ich habe noch etwas heraus gefunden. Wenn ich die Andwendung in VS2013 kompiliere und ausführe, arbeitet sie korrekt. Wenn ich dann in VS2013 die DLL erstelle und diese dann über meine GUI aufrufe, arbeitet sie wieder nicht korrekt. Hat das mti der Runtime zutun?

    Wenn ich die C# GUI in VS 2013 starte, arbeitet auch alles korrekt.



  • DirkB schrieb:

    CJens schrieb:

    realloc überschreibt übrigens keinen verwendeten Speicher. N[359].Gamma[3] ist im aktuellen Fall in Adresse 3 987 192 gespeichert.
    Der Speicher, welcher reserviert wird (bei npFace = 1) ist 3 987 248 - ist nur ein Feld, variiert natürlich bei jedem Ausführen.

    Wie kommst du an die Adressen?

    Hast du schon den Debugheap von VS benutzt?

    Die Adresse habe ich, indem ich diese über %i ausgebe.

    Nein, ich kenne keinen Debugheap. Werde das mal googeln.

    Gibt es da nativ was von Visual Studio oder muss man das in jedem Fall installieren?


Anmelden zum Antworten