SOLVED: Brauche einen Rat beim Debuggen...



  • Techel schrieb:

    In C brauchst du auch kein extern "C", ist ja schließlich schon C.

    Gelöst hat es das Problem leider nicht, habe das gemacht. Da hat mir der Compiler noch ein paar Sachen angezeigt. Die habe ich behoben. Das Problem besteht aber weiterhin.

    Also, Dateiendung ist jetzt *.c und alle extern "C" __declspec sind in extern __declspec abgeändert.



  • Wutz schrieb:

    Der Fehler sitzt vor dem Monitor und nicht im Compiler.

    Haha, der Fehler sitzt vor dem Monitor und nicht dahinter.



  • Ok, ich denke wir haben jetzt geklärt, dass malloc und realloc korrekt arbeiten. Ich habe das auch nie anders behauptet. Auch, dass der Fehler vor dem Monitor sitzt wurde ausführlich diskutiert. Das hat mir aber erstmal nicht wirklich weiter geholfen.

    Das Problem ist, dass durch ein malloc oder ein realloc ein komplett unabhängiger Wert überschrieben wird. Das kann ich kontrollieren, indem ich den Wert direkt vor dem malloc oder realloc und direkt danach durch ein printf ausgebe. Vielleicht verursacht auch das printf die Änderung, das weiß ich nicht. Und vor diesem Codeabschnitt laufen schon viele Seiten Code. Und da habe ICH wohl irgendwo einen Fehler gemacht. Und ich möchte einen Ratschlag, wie ich mich zu diesem Fehler hin arbeiten kann, denn ich habe keine Ahnung, wo das sein kann.

    Die Funktion selbst, in welcher der Codeabschnitt vorkommt, ist Teil einer räumlichen Octree-Zerlegung und läuft bei anderen Eingabedateien wunderbar. Die wird im Laufe des Codes mehrere tausend mal ausgeführt.

    printf("\t\tPre[%i]: N[359].Gamma[3]: %2.4e\n", i, N[359].Gamma[3]);/*Liefert "Pre[3]: N[359].Gamma[3] = 0.25e000"*/
    FB->FBox[i].F_Thread = (TFace**)realloc(FB->FBox[i].F_Thread, FB->FBox[i].npFace * sizeof(TFace*));
    printf("\t\tPost[%i]: N[359].Gamma[3]: %2.4e\n", i, N[359].Gamma[3]); /*Liefert z.B."Post[3]: N[359].Gamma[3] = 1.91e-208"*/
    

    N[359] ist der Knoten mit dem Index 359 - wie anfangs beschrieben, wird hier an einem 3D Gitter gearbeitet. Der wird in dieser Funktion eigentlich gar nicht bearbeitet, sondern wird statisch im Speicher gehalten. Die Funktion hier arbeitet an etwas komplett anderem. Ich konnte einfach durch Eingrenzen feststellen, dass der Wert an diesem Knoten im statischen Speicher an dieser Stelle verändert wird.



  • dass der Wert an diesem Knoten im statischen Speicher an dieser Stelle verändert wird.

    an welcher Stelle - bei den printfs? da wird doch gar nichts veraendert?
    ausser F_Thread durch das realloc

    Fragen/Tips:
    1. könnte es ein Threading-Problem sein - also konkurrierende Zugriffe oder sowas?

    2. auf welchem Kompiler/OS läuft dein C/C++ Backend? falls Linux(nur x64) mit gcc/clang geht könntest du mal den Address- und Thread-Sanitizer drauf los lassen - und damit schnell eine riesen Horde Fehler ausschliessen (die beiden Tools sind absolut Gold wert, Danke google)

    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)

    4. den Test in Release wie auch in Debug laufen lassen - gibts Unterschiede?

    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;
      ...
    }
    


  • Hier der Original-Code. Eine Menge an Flächen, wird anhand des Ortsvektors ihres Zentrums F->P.vx unterteilt. Nur zur Bildschirmausgabe wird das Gitter in Form der Struktur TMesh übergeben - wird NULL übergeben, erfolgt keine Bildschirmausgaben, da OutputLoc = 0. pNode ist die Menge von Knoten. Bei Knoten 359 tritt die Änderung auf.

    typedef struct TNode{
    	TPoint P;
    
    	struct TCell** EP;
    	double* Gamma;
    	unsigned int nEP;
    	struct TFace** FP;
    	unsigned int nFP;
    
    	unsigned long Index;
    	unsigned long Index2;
    	unsigned int Internal;
    }TNode;
    
    typedef struct TFace{
    	struct TPoint P;
    	struct TNode** ppNode;
    	struct TVector Normal;
    	struct TVector e;
    	struct TCell* E[2];
    
    	double Area;
    	double fP;
    	double MassFlow;
    	double MassFlow0;
    
    	double JacobiMatrix[3][3];
    	double TransformMatrix[3][3];
    	double JacobiDeterminante;
    	TNode* SecondJacobiNode;
    
    	unsigned int nNode;
    	unsigned long Index;
    	unsigned long Index2;
    	TVector vf;
    	TVector vf0;
    
    	struct TFamily* pFamily;
    }TFace;
    
    typedef struct FBBox{
    	TFace** F_Thread;
    	unsigned long npFace;
    
    	struct FBBox* FBox;
    
    	double XMin, XAve, XMax;
    	double YMin, YAve, YMax;
    	double ZMin, ZAve, ZMax;
    }FBBox;
    int SubdivideOneFBox(FBBox* FB, TMesh* M){
    #pragma region LocalVariables
    	unsigned long i = 0, j = 0, k = 0, l = 0, m = 0, n = 0, OutputLoc = 0;
    	TFace* F = NULL;
    	TFace** Dummy = NULL;
    #pragma endregion LocalVariables
    
    	if (FB->npFace <= 10){
    		return 0;
    	}
    
    	if (M != NULL) { OutputLoc = 1; }
    
    	FB->FBox = malloc(8 * sizeof(FBBox));
    	if (FB->FBox == NULL){ printf("ERROR - Unable to allocate memory!\n"); getchar(); return 1; }
    
    	for (i = 0; i < 8; i++){ 
    		FB->FBox[i].F_Thread = malloc(FB->npFace * sizeof(TFace*)); 
    		if (FB->FBox[i].F_Thread == NULL){ printf("ERROR - Unable to allocate memory!\n"); getchar(); return 1; }
    		FB->FBox[i].npFace = 0;
    	}
    
    	for (i = 0; i < FB->npFace; i++){
    		F = FB->F_Thread[i];
    
    		if (F->P.vx[0] > FB->XAve){ /*Box1, Box2, Box3, Box4*/
    			if (F->P.vx[1] > FB->YAve){ /*Box1, Box2*/
    				if (F->P.vx[2] > FB->ZAve){ /*Box1*/
    					FB->FBox[0].F_Thread[FB->FBox[0].npFace++] = F;
    				} else{ /*Box2*/
    					FB->FBox[1].F_Thread[FB->FBox[1].npFace++] = F;
    				}
    			} else{ /*Box3, Box4*/
    				if (F->P.vx[2] > FB->ZAve){ /*Box3*/
    					FB->FBox[2].F_Thread[FB->FBox[2].npFace++] = F;
    				}
    				else{ /*Box4*/
    					FB->FBox[3].F_Thread[FB->FBox[3].npFace++] = F;
    				}
    			}
    		}else{/*Box5, Box6, Box7, Box8*/
    			if (F->P.vx[1] > FB->YAve){ /*Box5, Box6*/
    				if (F->P.vx[2] > FB->ZAve){ /*Box5*/
    					FB->FBox[4].F_Thread[FB->FBox[4].npFace++] = F;
    				}else{ /*Box6*/
    					FB->FBox[5].F_Thread[FB->FBox[5].npFace++] = F;
    				}
    			}else{ /*Box7, Box8*/
    				if (F->P.vx[2] > FB->ZAve){ /*Box7*/
    					FB->FBox[6].F_Thread[FB->FBox[6].npFace++] = F;
    				} else{ /*Box8*/
    					FB->FBox[7].F_Thread[FB->FBox[7].npFace++] = F;
    				}
    			}
    		}
    	}
    
    	for (i = 0; i < 8; i++) {
    
    		if (OutputLoc == 1) { printf("\t\tPre[%i]: N[359].Gamma[3] = %2.4e\n", i, M->pNode[359].Gamma[3]);}
    		FB->FBox[i].F_Thread = (TFace**)realloc(FB->FBox[i].F_Thread, FB->FBox[i].npFace * sizeof(TFace*));
    		if (OutputLoc == 1) {printf("\t\tPost[%i]: N[359].Gamma[3] = %2.4e\n", i, M->pNode[359].Gamma[3]);}
    
    		switch (i){
    			case 0: /*Box 1*/
    				FB->FBox[i].XMin = FB->XAve;
    				FB->FBox[i].XMax = FB->XMax;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YAve;
    				FB->FBox[i].YMax = FB->YMax;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZAve;
    				FB->FBox[i].ZMax = FB->ZMax;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    			case 1: /*Box 2*/
    				FB->FBox[i].XMin = FB->XAve;
    				FB->FBox[i].XMax = FB->XMax;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YAve;
    				FB->FBox[i].YMax = FB->YMax;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZMin;
    				FB->FBox[i].ZMax = FB->ZAve;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    			case 2: /*Box 3*/
    				FB->FBox[i].XMin = FB->XAve;
    				FB->FBox[i].XMax = FB->XMax;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YMin;
    				FB->FBox[i].YMax = FB->YAve;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZAve;
    				FB->FBox[i].ZMax = FB->ZMax;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    
    				break;
    			case 3: /*Box 4*/
    				FB->FBox[i].XMin = FB->XAve;
    				FB->FBox[i].XMax = FB->XMax;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YMin;
    				FB->FBox[i].YMax = FB->YAve;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZMin;
    				FB->FBox[i].ZMax = FB->ZAve;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    			case 4: /*Box 5*/
    				FB->FBox[i].XMin = FB->XMin;
    				FB->FBox[i].XMax = FB->XAve;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YAve;
    				FB->FBox[i].YMax = FB->YMax;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZAve;
    				FB->FBox[i].ZMax = FB->ZMax;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    			case 5: /*Box 6*/
    				FB->FBox[i].XMin = FB->XMin;
    				FB->FBox[i].XMax = FB->XAve;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YAve;
    				FB->FBox[i].YMax = FB->YMax;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZMin;
    				FB->FBox[i].ZMax = FB->ZAve;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    			case 6: /*Box 7*/
    				FB->FBox[i].XMin = FB->XMin;
    				FB->FBox[i].XMax = FB->XAve;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YMin;
    				FB->FBox[i].YMax = FB->YAve;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZAve;
    				FB->FBox[i].ZMax = FB->ZMax;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    			default: /*Box 8*/
    				FB->FBox[i].XMin = FB->XMin;
    				FB->FBox[i].XMax = FB->XAve;
    				FB->FBox[i].XAve = .5 * (FB->FBox[i].XMax + FB->FBox[i].XMin);
    
    				FB->FBox[i].YMin = FB->YMin;
    				FB->FBox[i].YMax = FB->YAve;
    				FB->FBox[i].YAve = .5 * (FB->FBox[i].YMax + FB->FBox[i].YMin);
    
    				FB->FBox[i].ZMin = FB->ZMin;
    				FB->FBox[i].ZMax = FB->ZAve;
    				FB->FBox[i].ZAve = .5 * (FB->FBox[i].ZMax + FB->FBox[i].ZMin);
    				break;
    		}
    	}
    
    	free(FB->F_Thread);
    	//FB->npFace = 0;
    
    	return 0;
    }
    


  • ist es gewollt das in case 0: das break fehlt?

    case 0: /*Box 1*/ 
                    fbox.XMin = FB->XAve; 
                    fbox.XMax = FB->XMax; 
                    fbox.XAve = .5 * (fbox.XMax + fbox.XMin); 
    
                    fbox.YMin = FB->YAve; 
                    fbox.YMax = FB->YMax; 
                    fbox.YAve = .5 * (fbox.YMax + fbox.YMin); 
    
                    fbox.ZMin = FB->ZAve; 
                    fbox.ZMax = FB->ZMax; 
                    fbox.ZAve = .5 * (fbox.ZMax + fbox.ZMin); 
                case 1: /*Box 2*/ 
                    fbox.XMin = FB->XAve; 
                    fbox.XMax = FB->XMax; 
                    fbox.XAve = .5 * (fbox.XMax + fbox.XMin); 
    
                    fbox.YMin = FB->YAve; 
                    fbox.YMax = FB->YMax; 
                    fbox.YAve = .5 * (fbox.YMax + fbox.YMin); 
    
                    fbox.ZMin = FB->ZMin; 
                    fbox.ZMax = FB->ZAve; 
                    fbox.ZAve = .5 * (fbox.ZMax + fbox.ZMin); 
                    break;
    


  • und räum mal auf

    fbox.XMin = FB->XAve; 
                    fbox.XMax = FB->XMax; 
                    fbox.XAve = .5 * (fbox.XMax + fbox.XMin); 
    
                    fbox.YMin = FB->YAve; 
                    fbox.YMax = FB->YMax; 
                    fbox.YAve = .5 * (fbox.YMax + fbox.YMin); 
    
                    fbox.ZMin = FB->ZAve; 
                    fbox.ZMax = FB->ZMax; 
                    fbox.ZAve = .5 * (fbox.ZMax + fbox.ZMin);
    
    set_fbox_xyz(FBox*, XMin, XMax, XAve, YMin, YMax, YAve, ...)
    
    set_fbox_xyz
    (
     fbox, 
     FB->XAve, FB->XMax, .5 * (fbox.XMax + fbox.XMin, 
     FB->YAve, FB->YMax, .5 * (fbox.YMax + fbox.YMin),
     FB->ZAve, FB->ZMax, .5 * (fbox.ZMax + fbox.ZMin),
    );
    

    macht daraus viele Einzeiler - und dann kann man leichter Fehler finden



  • Gast3 schrieb:

    dass der Wert an diesem Knoten im statischen Speicher an dieser Stelle verändert wird.

    an welcher Stelle - bei den printfs? da wird doch gar nichts veraendert?
    ausser F_Thread durch das realloc

    Das ist es ja. Der Knotenwert wird nicht mal an die Funktion übergeben. Ich mache das hier nur, um den Wert überwachen zu können.

    Gast3 schrieb:

    Fragen/Tips:
    1. könnte es ein Threading-Problem sein - also konkurrierende Zugriffe oder sowas?

    Nein. Ich Nutze zwar Threading, hab das dann aber zu Testzwecken deaktiviert und führe die Funktion direkt im Code aus.

    Gast3 schrieb:

    2. auf welchem Kompiler/OS läuft dein C/C++ Backend? falls Linux(nur x64) mit gcc/clang geht könntest du mal den Address- und Thread-Sanitizer drauf los lassen - und damit schnell eine riesen Horde Fehler ausschliessen (die beiden Tools sind absolut Gold wert, Danke google)

    Beides Visual Studio 2015 - Windows 7 64 Bit. Hab als platform x64 gewählt.

    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!!" 😋

    Gast3 schrieb:

    4. den Test in Release wie auch in Debug laufen lassen - gibts Unterschiede?

    Kein Unterschied...

    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.



  • Gast3 schrieb:

    ist es gewollt das in case 0: das break fehlt?

    case 0: /*Box 1*/ 
                    fbox.XMin = FB->XAve; 
                    fbox.XMax = FB->XMax; 
                    fbox.XAve = .5 * (fbox.XMax + fbox.XMin); 
      
                    fbox.YMin = FB->YAve; 
                    fbox.YMax = FB->YMax; 
                    fbox.YAve = .5 * (fbox.YMax + fbox.YMin); 
      
                    fbox.ZMin = FB->ZAve; 
                    fbox.ZMax = FB->ZMax; 
                    fbox.ZAve = .5 * (fbox.ZMax + fbox.ZMin); 
                case 1: /*Box 2*/ 
                    fbox.XMin = FB->XAve; 
                    fbox.XMax = FB->XMax; 
                    fbox.XAve = .5 * (fbox.XMax + fbox.XMin); 
      
                    fbox.YMin = FB->YAve; 
                    fbox.YMax = FB->YMax; 
                    fbox.YAve = .5 * (fbox.YMax + fbox.YMin); 
      
                    fbox.ZMin = FB->ZMin; 
                    fbox.ZMax = FB->ZAve; 
                    fbox.ZAve = .5 * (fbox.ZMax + fbox.ZMin); 
                    break;
    

    Danke für den Hinweis. Wieso hat das nichts ausgelöst? Hab es korrigiert, der Fehler besteht aber weiterhin.



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



  • 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?


Anmelden zum Antworten