Fehlermeldung bei Verwendung von ifstream



  • Hallo zusammen,

    warum bekomme ich mit diesem Beispiel (C++Builder 2010) eine Fehlermeldung 😕
    Wo hab ich denn da einen Überlauf ? Die Fehlermeldung kommt schon beim Aufrufen der Zeile 26.

    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <iostream>
    #include <fstream>
    #include <string>
    #pragma hdrstop
    
    #include "Unit1.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    using namespace std;
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     string strZeile;
    
     ifstream SrcFile( SourceEdt->Text.c_str(), ios::in | ios::binary );
     //if ( SrcFile.good() )
     if ( SrcFile != 0 )
       {
    	ListBox1->Items->Add ( "Öffne Datei " + SourceEdt->Text );
    	while ( !SrcFile.eof() )
    	  {
    	   getline( SrcFile, strZeile );
    	   ListBox1->Items->Add( strZeile.c_str() );
    	  }
       }
     else
       {
    	ListBox1->Items->Add ( "Kann Datei " + SourceEdt->Text + " nicht öffnen !" );
    	return;
       }
     SrcFile.close();
    }
    //---------------------------------------------------------------------------
    

    Fehlermeldung:

    05.01.2011 16:07:36 CodeGuard(tm)-Prozess wurde gestartet: Test.exe(508) 
    Zugriff Überlauf im Prozess: Test.exe(508)  - c:\program files\embarcadero\rad studio\7.0\include\../include/dinkumware/fstream#157
      Versuch auf 520 Byte(s) bei 0x01CAFDAC zuzugreifen, das ist bei Offset 12 in Heap block 0x01CAFDA0, der nur 38 Byte lang ist.
      0x004CFB2C Aufruf von wcstombs(0x0012F190 ["J�\f��"], 0x01CAFDAC, 0x104 [260])
        0x004B76FE
        0x00403184 - c:\program files\embarcadero\rad studio\7.0\include\../include/dinkumware/fstream#157
        0x00402709 - c:\program files\embarcadero\rad studio\7.0\include\../include/dinkumware/fstream#647
        0x00401F36 - Unit1.cpp#27
        0x004A7ED9 - Controls.pas#7179
        0x004AC235 - Controls.pas#9821
      Speicherblock (0x01CAFDA0) [Größe: 38 Byte] war Bereitgestellt mit SysGetMem
        0x0044B29A - System.pas#2983
        0x004A7ED9 - Controls.pas#7179
        0x004AC235 - Controls.pas#9821
        0x00463ABD - StdCtrls.pas#4365
        0x004AC388 - Controls.pas#9888
        0x004AC235 - Controls.pas#9821
    


  • Hab das Problem gefunden, aber noch nicht verstanden. Wenn ich folgende Zeile ändere funktioniert es:

    // geht nicht
    ifstream SrcFile( SourceEdt->Text.c_str(), ios::in | ios::binary );
    // so funktioniert es
    ifstream SrcFile( "C:\\Temp\\Testfile.txt", ios::in | ios::binary );
    

    Wieso kann das nicht aus dem Edit-Feld ausgelesen werden ? Liegt das am "c_str()" ?



  • auf meinem CBuilder 6 geht das ohne Probleme.
    Versuche es doch mal so:

    ifstream SrcFile;
      SrcFile.open(SourceEdt->Text.c_str() , ios::in | ios::binary );
    

    Gruß myerscola



  • myerscola schrieb:

    auf meinem CBuilder 6 geht das ohne Probleme.

    Der hat auch kein Unicode. Beim BCB 6 gilt String = AnsiString, seit 2009 String = UnicodeString.

    Versuch mal

    AnsiString(SourceEdt->Text).c_str()
    


  • Hi nn,

    das war der Knackpunkt, damit geht's. Aber verstehen tu ich es nicht, selbst diese beiden Versionen funktionieren nicht:

    // hier kommt zwar kein Abbruch, aber NULL Pointer zurück
    ifstream SrcFile( SourceEdt->Text.t_str(), ios::in | ios::binary );
    // selbst mit der "Unicode" Version von ifstream geht es auch nur über AnsiString()
    wifstream SrcFile( SourceEdt->Text.c_str(), ios::in | ios::binary );
    

    Wäre das eine "korrekte" Unicode Variante mit wifstream ? getline() ?

    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     wstring strZeile;
    
     wifstream SrcFile( AnsiString( SourceEdt->Text ).c_str(), ios::in | ios::binary );
     if ( SrcFile.good() )
       {
        ListBox1->Items->Add ( "Öffne Datei " + SourceEdt->Text );
        while ( !SrcFile.eof() )
          {
           getline( SrcFile, strZeile );
           ListBox1->Items->Add( strZeile.c_str() );
          }
       }
     else
       {
        ListBox1->Items->Add ( "Kann Datei " + SourceEdt->Text + " nicht öffnen !" );
        return;
       }
     SrcFile.close();
    }
    


  • Verstehen tue ich es auch nicht ganz, ich habe gerade keinen C++ Builder in Reichweite, muss das bei Gelegenheit mal testen.

    ifstream und wifstream sollten eigentlich beide char* oder wchar_t* als Dateinamen akzeptieren. Jedenfall tuen sie es bei der Konkurenz:
    http://msdn.microsoft.com/de-de/library/zek0beca.aspx

    t_str() soll man übrigens nicht benutzen:
    http://blogs.embarcadero.com/ddean/2010/09/10/34867



  • nn schrieb:

    Verstehen tue ich es auch nicht ganz, ich habe gerade keinen C++ Builder in Reichweite, muss das bei Gelegenheit mal testen.

    ifstream und wifstream sollten eigentlich beide char* oder wchar_t* als Dateinamen akzeptieren. Jedenfall tuen sie es bei der Konkurenz:

    Laut C++ Standard akzeptiert der ifstream-Konstruktor nur const char* für den Filenamen aber kein wchar_t*. Scheint also eine MS-Erweiterung zu sein.



  • Dann hätte ich aber eine Fehlermeldung erwartet, wenn eine Funktion const char* erwartet, aber const wchar_t* bekommt ...



  • So, ich konnte es jetzt mit dem 2010er testen ...

    Braunstein schrieb:

    Laut C++ Standard akzeptiert der ifstream-Konstruktor nur const char* für den Filenamen aber kein wchar_t*. Scheint also eine MS-Erweiterung zu sein.

    Er geht aber nach

    explicit basic_ifstream(const wchar_t *_Filename,
    		ios_base::openmode _Mode = ios_base::in,
    		int _Prot = (int)ios_base::_Openprot)
    		: basic_istream<_Elem, _Traits>(&_Filebuffer)
    		{	// construct with wide-named file -- EXTENSION
    		if (_Filebuffer.open(_Filename, _Mode | ios_base::in, _Prot) == 0)
    			_Myios::setstate(ios_base::failbit);
    		}
    

    im fstream Header.

    Deshalb sagt der Compiler also nix.

    Und das

    void __fastcall TfrmMain::btnStreamClick(TObject *Sender)
    {
    	String name = L"Test.txt";
    
    	string s;
    	ifstream dat(name.c_str());
    
    	while (!dat.eof())
    	{
    		getline(dat, s);
    	}
    }
    

    läuft ohne Probleme.



  • Hmm, das ergibt bei mir den gleichen Fehler. Allerdings nur, wenn ich unter C++Compiler->Debuggen->Codeguard aktivieren = true gesetzt habe 😕
    Compilieren macht er ohne Fehlermeldung, nur beim Ausführen kommt wieder die Fehlermeldung vom Codeguard. Wenn ich den Codeguard deaktiviere läuft das Programm durch ?!

    void __fastcall TfrmMain::btnStreamClick(TObject *Sender)
    {
        String name = L"Test.txt";
    
        string s;
        ifstream dat(name.c_str());
    
        while (!dat.eof())
        {
            getline(dat, s);
        }
    }
    
    11.01.2011 08:30:44 CodeGuard(tm)-Prozess wurde gestartet: Test.exe(4640) 
    Zugriff Überlauf im Prozess: Test.exe(4640) 
      Versuch auf 520 Byte(s) bei 0x01CEF56C zuzugreifen, das ist bei Offset 12 in Heap block 0x01CEF560, der nur 38 Byte lang ist.
      0x004E4040 Aufruf von wcstombs(0x0012EB74 ["��"], 0x01CEF56C, 0x104 [260])
        0x004CEDEA
        0x0040ED81
        0x004BF5C5
        0x004C3921
        0x0047B1A9
        0x004C3A74
      Speicherblock (0x01CEF560) [Größe: 38 Byte] war Bereitgestellt mit SysGetMem
        0x0045E60E
        0x004EA405
        0x0040DB50
        0x004BF5C5
        0x004C3921
        0x0047B1A9
    


  • Da müsste man mal den Code anschauen, ob da bei der Zeichensatzumwandlung falsch auf Speicher zugegriffen wird, oder der Fehler in Codeguard liegt.

    Aber wenn da intern wcstombs aufgerufen wird, kannst du auch gleich die Variante mit dem AnsiString nehmen, die macht die gleiche Umwandlung, nur an anderer Stelle.



  • nn schrieb:

    So, ich konnte es jetzt mit dem 2010er testen ...

    Braunstein schrieb:

    Laut C++ Standard akzeptiert der ifstream-Konstruktor nur const char* für den Filenamen aber kein wchar_t*. Scheint also eine MS-Erweiterung zu sein.

    Er geht aber nach
    ...
    läuft ohne Probleme.

    Das widerspricht doch in keiner Weise meiner Aussage. Die Compilerhersteller haben doch durchaus die Möglichkeit die Standardbibliotheken über den Standard hinaus zu erweitern.



  • Braunstein schrieb:

    Das widerspricht doch in keiner Weise meiner Aussage.

    Aber der Doku vom Builder 2010.



  • nn schrieb:

    Da müsste man mal den Code anschauen, ob da bei der Zeichensatzumwandlung falsch auf Speicher zugegriffen wird, oder der Fehler in Codeguard liegt.

    Aber wenn da intern wcstombs aufgerufen wird, kannst du auch gleich die Variante mit dem AnsiString nehmen, die macht die gleiche Umwandlung, nur an anderer Stelle.

    Naja an Code ist da nichts weiters drin als dieser Button-Click. Dann liegt es wohl tatsächlich an dem Codeguard und es ist kein Fehler im Programm-Code.
    Wenn ich im normalen Debug Modus das Programm erzeuge geht es auch, nur mit Codeguard aktiviert bringt er diesen Fehler. Ich dachte mit Codeguard sollte ein fehlerfreier Programm-Code immer durchlaufen 😞



  • Ich habe das selbe Problem mit Codegard......ist traurig aber wahr.

    Kennt vllt jmd eine Prgama-Anweisung um Codegard für einzelne Zeilen auszuschalten?


Anmelden zum Antworten