Ist C++ weiblich?



  • Hallo Profis,

    ich schreibe gerade ein etwas umfangreicheres (für meine Verhältnisse) Programm in C++ und bin an einem Punkt, wo ich meinen Glauben zu Verlieren drohe.

    Das Programm läuft, wenn ich am Anfang des Programms eine Ausgabe auf der Kommandozeile mache... wenn nicht, kommt eine Zugriffs-Exception.

    Anbei der Code-Ausschnitt (die komplette Routine am Ende):

    int main(){
    	//Lokal variables
    	char **Puffer = NULL; unsigned long nPuffer = 0;
    	unsigned long EndLineNode = 0, EndLineBar = 0,  EndLineFace = 0, EndLineElement = 0, MaxExternalNodeNumber = 0;
    	string *SPuffer = NULL, line;
    	unsigned long fi = 0, fj = 0, fk = 0, fl = 0, nLines = 0;
    	time_t start = time(NULL), stop;
    	unsigned long NeedSeconds = 0;
    
    	cout << ++fk << endl; //Hier ist die Kommandozeilenausgabe!!!!
    
    	//Try to open file...
    	fstream MeshFile;
    	MeshFile.open(MeshFileName, ios::in);
    
    	//Checking if file is opened...
    	if (!MeshFile){return 1;}
    
    	//Getting Size of Meshfile
    	nLines = MyFileFunctions::GetNastranLineNumber(MeshFileName, 81);
    
    	//Allocating memory to store file containment
    	Puffer = (char**)calloc(nLines, sizeof(char*));
    	if (Puffer == NULL){ return 2; }
    
    //Und so weiter...
    

    So läuft der Code wunderbar. Kommentiere ich die Zeile

    cout << ++fk << endl;
    

    aus, dann plopt auf einmal ein Fenster von crtexe.c auf und springt zu folgender Codestelle:

    #ifdef WPRFLAG
                mainret = wWinMain(
    #else  /* WPRFLAG */
                mainret = WinMain(
    #endif  /* WPRFLAG */
                           (HINSTANCE)&__ImageBase,
                           NULL,
                           lpszCommandLine,
                           showWindowMode
                          );
    #else  /* _WINMAIN_ */
    
    #ifdef WPRFLAG
                __winitenv = envp;
                mainret = wmain(argc, argv, envp);
    #else  /* WPRFLAG */
                __initenv = envp;
                mainret = main(argc, argv, envp);
    #endif  /* WPRFLAG */
    
    #endif  /* _WINMAIN_ */
    

    Darüber hinaus kommt eine Fehlermeldung:
    Ausnahmefehler bei 0x01183CF in Main.exe: 0xC0000005:
    Zugriffsverletzung beim Lesen an Position 0xFC874A2C

    Ok, er greift wohl auf Speicher zu, auf den er nicht zugreifen darf.
    Kann es sein, dass ++fk nur dazu führt, dass er weiterhin auf falschen, aber
    les/beschreibbaren Speicher zugreift?

    Sowas habe ich auch noch nicht erlebt...

    Zusatz:
    Also, ich konnte beobachten, dass der Fehler auch unabhängig vom Auskommentieren auftritt, wenn ich die Optimierungsstufe hochschraube und damit verbunden die Laufzeitkontrolle deaktiviere.

    Darüber hinaus tritt der Fehler erst im späteren Verlauf des Programms auf...



  • CJens schrieb:

    Hallo Profis,

    ich schreibe gerade ein etwas umfangreicheres (für meine Verhältnisse) Programm in C++ und bin an einem Punkt, wo ich meinen Glauben zu Verlieren drohe.

    Das Programm läuft, wenn ich am Anfang des Programms eine Ausgabe auf der Kommandozeile mache... wenn nicht, kommt eine Zugriffs-Exception.

    Anbei der Code-Ausschnitt (die komplette Routine am Ende):

    int main(){
    	//Lokal variables
    	char **Puffer = NULL; unsigned long nPuffer = 0;
    	unsigned long EndLineNode = 0, EndLineBar = 0,  EndLineFace = 0, EndLineElement = 0, MaxExternalNodeNumber = 0;
    	string *SPuffer = NULL, line;
    	unsigned long fi = 0, fj = 0, fk = 0, fl = 0, nLines = 0;
    	time_t start = time(NULL), stop;
    	unsigned long NeedSeconds = 0;
    
    	cout << ++fk << endl; //Hier ist die Kommandozeilenausgabe!!!!
    
    	//Try to open file...
    	fstream MeshFile;
    	MeshFile.open(MeshFileName, ios::in);
    		
    	//Checking if file is opened...
    	if (!MeshFile){return 1;}
    
    	//Getting Size of Meshfile
    	nLines = MyFileFunctions::GetNastranLineNumber(MeshFileName, 81);
    
    	//Allocating memory to store file containment
    	Puffer = (char**)calloc(nLines, sizeof(char*));
    	if (Puffer == NULL){ return 2; }
    
    //Und so weiter...
    

    So läuft der Code wunderbar. Kommentiere ich die Zeile

    cout << ++fk << endl;
    

    aus, dann plopt auf einmal ein Fenster von crtexe.c auf und springt zu folgender Codestelle:

    #ifdef WPRFLAG
                mainret = wWinMain(
    #else  /* WPRFLAG */
                mainret = WinMain(
    #endif  /* WPRFLAG */
                           (HINSTANCE)&__ImageBase,
                           NULL,
                           lpszCommandLine,
                           showWindowMode
                          );
    #else  /* _WINMAIN_ */
    
    #ifdef WPRFLAG
                __winitenv = envp;
                mainret = wmain(argc, argv, envp);
    #else  /* WPRFLAG */
                __initenv = envp;
                mainret = main(argc, argv, envp);
    #endif  /* WPRFLAG */
    
    #endif  /* _WINMAIN_ */
    

    Darüber hinaus kommt eine Fehlermeldung:
    Ausnahmefehler bei 0x01183CF in Main.exe: 0xC0000005:
    Zugriffsverletzung beim Lesen an Position 0xFC874A2C

    Ok, er greift wohl auf Speicher zu, auf den er nicht zugreifen darf.
    Kann es sein, dass ++fk nur dazu führt, dass er weiterhin auf falschen, aber
    les/beschreibbaren Speicher zugreift?

    Sowas habe ich auch noch nicht erlebt...

    Zusatz:
    Also, ich konnte beobachten, dass der Fehler auch unabhängig vom Auskommentieren auftritt, wenn ich die Optimierungsstufe hochschraube und damit verbunden die Laufzeitkontrolle deaktiviere.

    Der Fehler tritt auf, bevor das Programm startet. Eigentlich wollte ich mit den couts feststellen, wo das Programm abstürzt... und dann hab ich es durch Holding-Points versucht... aber er kommt nichtmal zu ersten (der Anfang)...

    Sorry für das Doppelposting - wollte editieren, nicht zitieren 😞



  • Nun es liegt wohl daran, dass du manuell Speicher verwaltest (und das sogar mit C-Funktionen!).
    Ich schätze mal, dass du dir via *alloc Speicher für einen std::string holst. Dabei wird aber kein Konstruktor aufgerufen, dass string-Objekt ist somit kaputt und - peng!

    Edit: Auch sonst programmierst du in C++ so, als wäre es noch C.
    Variablen kann man in C++ erst dann erstellen, wenn man sie wirklich benötigt und nicht am Anfang von main. Zur Fehlerbehandlung verwendet man auch normalerweise Exceptions und keine Fehlercodes.



  • ...aber die Deklaration von SPuffer als String ist ohne Funktion. Ich habe es vorher mal auch mit Strings versucht... bin dann aber beim Char-Array geblieben, da ich später eine Datei lese (und das möglichst schnell) die formatiert ist.

    Also...

    string *SPuffer = NULL, line;
    

    ...können wir auch gerne aus dem Code löschen und alle Strings.

    Ja, ich habe lange natives C programmiert und steige jetzt wegen der Parallelisierungsmöglichkeiten und der Kompatibilität zu C# um.



  • Dann müssen wir mehr Code sehen.

    da ich später eine Datei lese (und das möglichst schnell) die formatiert ist

    Nimm trotzdem std::string. Der Code ist einfacher, exception sicherer, bugfreier und mit guter Wahrscheinlichkeit sogar schneller.
    Außerdem wird die meiste I/O-Zeit damit verbracht, die eigentlichen rohen Daten zu lesen, anstatt die Neuinterpretation danach (80-20-Rule btw).


Anmelden zum Antworten