Die Sache strncpy/memcpy



  • Hallo zusammen,

    Ich komme gerade nicht bei meinem Programm weiter, welches eine Datei öffnen , die Zeile in einer ausgelagerten Funktion vergleichen soll und diese bei Erfolg in dem Array

    LRED[LREDP]
    LREDP // Counter der Felder
    

    speichern soll. Das funltioniert aber nicht, da dann sofort meine App crasht. Soll ich dafür strncpy oder memcpy benutzen?
    Und warum funktioniert

    LRED[LREDP] = lineBuffer;
    

    nicht? Sobald ich das nämlich verwende, ist auf einmal jede Zeile, welcher in lineBuffer gespeichert ist in LRED[LREDP]?!

    #include <windows.h>
    #include <tchar.h>
    #include <fstream>
    #include <string.h>
    #include <stdlib.h>
    #include <malloc.h>
    using namespace std;
    
    int _tmain( int argc, _TCHAR* argv[] )
    {
    	// Deklarationen
    	unsigned int *LREDNum;
    	int LREDP = 0, i;
    	char **LRED;
    	char lineBuffer[512];
    	char file[512];
    
    	LRED = (char**) malloc( MINCYCLEHITS * sizeof(char*) );
    	LREDP = (unsigned int*) malloc( MINCYCLEHITS * sizeof(int*) );
    
    	FILE *stream;
    	fopen_s( &stream, file, "r" );
    
    	// Pruefen, ob Stream existiert
    	if( stream != NULL )
    	{
    		// Datei Zeilenweise durchlaufen
    		while( !feof( stream ) )
    		{
    			// Puffer leeren
    			strcpy_s( lineBuffer, sizeof( lineBuffer ), "" );
    
    			/ Zeile einlesen
    			fgets( lineBuffer, sizeof( lineBuffer ) - sizeof( lineBuffer[0] ), stream );
    
    			// Zeilenumbruch loeschen
    			if( lineBuffer[ strlen(lineBuffer)-1 ] == '\n' )
    				lineBuffer[ strlen(lineBuffer)-1 ] = 0x0;
    
    			// String Null-Terminieren
    			lineBuffer[512-1] = '\0';
    			if( ThisFleLine(profileFile, lineBuffer) )
    			{
    				// Array erweitern
    				if( LREDP == MINCYCLEHITSB )
    				{
    					LRED = (char**) realloc( LRED, LREDP * sizeof(LRED[0]) );
    					LREDP = (unsigned int*) realloc( LREDNum, LREDP * sizeof(int) );
    				}
    
    				LREDP[LREDP] = row;
    				strncpy_s(LRED[LREDP], 512, lineBuffer, _TRUNCATE);
                    (*LRED)[512-1] = '\0';
    				LREDP++;
    			}
    			// Inkrementieren der aktuellen Zeilennummer
    			row++;
    		}
    		// Stream schliessen
    		fclose(stream);
    
    		// Speicher freigeben
    		free(LRED);
    		free(LREDNum);
    	}
    	return 0;
    }
    

    Ich hoffe ihr könnte mir helfen.

    Ciao,
    Thindia80



  • Wenns ein String ist (und das isses ja), nimm strcpy/strncpy.



  • Wie würde der Aufruf bei strcpy_s(); aussehen?

    Ich habe das schon ohne Erfolg so probiert:

    strcpy_s(LRED[LREDP], sizeof(char[512]), lineBuffer);
    

    Lg,
    Thindia80



  • Habe mich jetzt doch für strncpy entschienden.

    Habe mir auch schon die MSDN dazu durchgelesen und das
    in meinem Programm ausprobiert, jedoch ihne erfolg.

    Kann mir bitte jemand die passenden Variablen in strncpy
    einfügen und das dann posten pls?

    Liebe Grüße

    Thindia80



  • Kann mir bitte jemand helfen, ich habe schon Studen vor dem Problemcodebaustein verbracht - leider ohne Erfolg.

    Bitte, bitte, bitte, ich komme sonst nicht weiter.

    Thindia80



  • Grundsätzlich die wichtigsten Fragen:
    Wie crasht denn Deine App? Fehlermeldung?
    Kannst Du einen Debugger anwerfen?

    Nun, hab mir mal ein bißchen durch Dein Code gelesen.

    Folgendes ist mir aufgefallen:

    LRED = (char**) malloc( MINCYCLEHITS * sizeof(char[512]) );
    LRED = (char**) malloc( MINCYCLEHITS * sizeof(char[512]) );
    

    Warum zweimal?
    Unabhängig davon, da Du den ersten zurückgegebenen Pointer beim zweiten Mal verloren hast, kannst Du den ersten allokierten Speicher nie mehr freigeben!

    // String Null-Terminieren
    lineBuffer[ strlen( lineBuffer ) ] = '\0';
    

    Das ist sehr gefährlich! Denn strlen() kann nur sicher funktionieren, wenn sichergestellt ist, daß lineBuffer bereits eine Nullterminierung enthält!
    Was aber in diesem Falle absurd ist.
    Also besser so:

    // Zeile einlesen
    fgets( lineBuffer, sizeof( lineBuffer ) - sizeof( lineBuffer[0] ), stream );
                       //Ein Zeichen weniger einlesen als die Buffergröße selbst, da Platz für die Nullterminierung benötigt wird!
    
    // String Null-Terminieren
    lineBuffer[512-1] = '\0';
    
    if( ThisFleLine(profileFile, lineBuffer) )
    

    Was macht denn diese Funktion ThisFleLine()?
    Geschweige denn, was ist profileFile ???

    Und last but not least:
    Was ist eigentlich MINCYCLEHITS?

    Martin



  • Hallo Mmacher,

    ich habe jetzt deine Änderungen in meinen Source eingebaut und diesen editiert.

    Meine App crasht mit der Meldung: "Unbehandelte Ausnahme in Compare.exe [1548]."

    Der Just-In-Time-Debugger von VS2005 meldet mir den folgenden Fehler:

    Compare.exe!strncpy_s(char * _Dst=0xcdcdcdcd, unsigned int _SizeInBytes=512, const char * _Src=0x0012fb34, unsigned int _Count=4294967295)  Zeile 37 + 0x8 Bytes	C
    
    ThisFleLine(char* profileFile, char* profileFile);
    

    Die Funktion überprüft, ob der String mit einem anderen aus einer anderen Datei übereinstimmt.
    Darin kann der Fehler nicht liegen.

    MINCYCLEHITS
    

    Ist eine Deininition für den Precompiler, welches den Wert 2 hat.

    Vielen Dank für deine bisherige Hilfe Mmacher. Du hast mir damit schon sehr weitergeholfen.

    Lg,
    Thindia80


  • Mod

    Ja und. Dann schau in den Callstack und Du siehst wo es krachtund wo die Zeiger und Variablen stehen.

    Für was denkst Du gibt es einen Debugger?



  • Thindia80 schrieb:

    Compare.exe!strncpy_s(char * _Dst=0xcdcdcdcd, unsigned int _SizeInBytes=512, const char * _Src=0x0012fb34, unsigned int _Count=4294967295)  Zeile 37 + 0x8 Bytes	C
    

    Sieh dir mal deinen Zielpuffer an (0xcdcdcdcd). Du übergibst einen Zeiger, dem du gar keinen Speicher zugewiesen hast.

    Wenn du so einen Zeiger deklarierst

    char *pString;
    

    Dann kannst du da noch lange nicht reinschreiben. Das ist nur ein Zeiger, der zeigt aber auf nix. Du musst Speicher reservieren mit malloc oder new. Lies dir mal die Artikel auf dieser Webseite zu den Themen Pointer und Speicherverwaltung durch.

    Thindia80 schrieb:

    ThisFleLine(char* profileFile, char* profileFile);
    

    Die Funktion überprüft, ob der String mit einem anderen aus einer anderen Datei übereinstimmt.
    Darin kann der Fehler nicht liegen.

    Kommt ganz drauf an, wie die Funktion aussieht...



  • Aber in meinem oben genanntem Source Reserviere ich doch Speicher mit

    LRED = (char**) malloc( MINCYCLEHITS * sizeof(char*) );
        LREDP = (unsigned int*) malloc( MINCYCLEHITS * sizeof(int*) );
    

    Ich bitte einfach, mir den Fehler zu zeigen. Ich habe echt Respekt vor den ganzen C++ Gurus hier, muss mir aber selbst eingestehen leider nicht dazuzugehören - noch nicht.

    Einen schönen Abend,

    Thindia80



  • Na ja, was soll denn überhaupt LREDP sein? Du deklarierst diese Variable als int (also nicht als Zeiger), weist ihr dann aber die Rückgabe von malloc/realloc (also eine Adresse!) zu. Und dann wiederum benutzt du sie als Index für LRED. Das kann ja nur schiefgehen.

    int LREDP=0;
    ...
    LREDP=malloc... //hier wird eine Speicheradresse zugewiesen, z.B. 0x12345678
    ...
    strncpy_s(LRED[LREDP], 512, lineBuffer, _TRUNCATE);  //hier schreibst du jetzt an die Stelle LRED[0x12345678]
    

    Nicht ganz, was du willst, oder? Lass bei LREDP einfach mal den ganzen malloc-Quatsch weg, dann wird die Variable mit 0 initialisiert und später in der Schleife inkremeniert, was du vermutlich eher willst (oder?).


Log in to reply