Zugriffsverletzung bei sprintf
-
Hallo C++-Community,
ich habe mir eine Methode geschrieben die das aktuelle Datum in einem char* zurückgeben soll.
Bei sprintf() bekomm ich immer folgenden Ausnahmefehler (Exception):Unbehandelte Ausnahme bei 0x5da1a669 (msvcr90d.dll) in FirstPTest.exe: 0xC0000005: Zugriffsverletzung beim Schreiben an Position 0x5fce688c.
Ich hab auch schon ordendlich gegoogelt, allesmögliche durchprobiert, bringt irgendwie alles nichts...
Hier mein Code:******_API char* FPGetDateString(void) { char* result = "00.00.0000"; SYSTEMTIME systime; GetSystemTime(&systime); sprintf(result, "%d.%d.%d", systime.wDay, systime.wMonth, systime.wYear); return result; } *******_API char* FPGetTimeString(bool seconds) { char* result = "00:00"; SYSTEMTIME systime; GetSystemTime(&systime); if (seconds) sprintf(result, "%d:%d.%d", systime.wHour, systime.wMinute, systime.wSecond); else sprintf(result, "%d:%d", systime.wHour, systime.wMinute); return result; }
Ich habe keine Methode die das Datum so ausgibt gefunden, falls es doch eine gibt, bitte melden
Sieht jemand den Fehler?
mfg.
markus111
-
Result zeigt auf ein Stringliteral.
-
Danke für die Schnelle Antwort - aber ich versteh nicht ganz was du meinst
-
Ein Stringliteral - also sowas wie
"00:00"
darf nicht verändert werden, was du mitsprintf()
aber tust.Wenn du dein Fast-C-Level beibehalten willst, musst du manuell Speicher anfordern und diesen zurückgeben. Das ist jedoch gefährlich, weil man als Aufrufer an die Freigabe denken muss.
Als C++-Programmierer empfehle ich daher, RAII einzusetzen und das Array in einer Klasse zu kapseln. Zum Beispiel mit
std::vector<char>
, damit bleibst du auch kompatibel zu C-Schnittstellen. Oder du baust dir selber was.
-
Hmm, so wird doch nicht auf ein Stringliteral zugegriffen, oder?
*******_API char* FPGetDateString(void) { char result [100]; SYSTEMTIME systime; GetSystemTime(&systime); sprintf(result, "%d.%d.%d", systime.wDay, systime.wMonth, systime.wYear); return result; } *******_API char* FPGetTimeString(bool seconds) { char result [100]; SYSTEMTIME systime; GetSystemTime(&systime); if (seconds) sprintf(result, "%d:%d.%d", systime.wHour, systime.wMinute, systime.wSecond); else sprintf(result, "%d:%d", systime.wHour, systime.wMinute); return result; }
Zu deiner Empfehlung: ich guck mal
mfg.
markus111
-
Nein, aber so gibst du einen Zeiger auf ein lokales Objekt zurück, das ist auch nicht besser. Deshalb musst du den Speicher entweder kopieren oder etwas Dynamisches zurückgeben.
-
Dieser Thread wurde von Moderator/in pumuckl aus dem Forum C++ in das Forum ANSI C verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Ich komm damit nicht ganz kla...
Könnte jemand vllt. für mich das umschreiben, das es funzt
ist vllt. nicht so nach den Forensregeln vorgesehn, aber ich komm so nich weiter
mfg.
maruks111
-
Als schnelle Hilfe könntest du ersteinmal den Puffer statisch machen:
static char result[100];
Du mußt dann nur aufpassen, daß nachfolgende Aufrufe den Puffer überschreiben:
char *cDate1 = FPGetDateString(); // ... char *cDate2 = FPGetDateString(); // cDate1 und cDate2 zeigen nun auf den selber Inhalt (den des letzten Aufrufs)
Wenn du jedoch C++ programmieren willst, so solltest du die Klassen std::string (statt char*) sowie std::stringstream (statt sprintf) einsetzen...
-
Wenn du jedoch C++ programmieren willst...
Dazu solltest du Stellung nehmen. Die Freunde in der C++-Ecke haben angenommen, dass du das mit reinem C machen willst, und dich hierher verschoben. Hier nehmen wir aber üblicherweise an, dass wir kein C++ zu Verfügung haben.
Nein, aber so gibst du einen Zeiger auf ein lokales Objekt zurück, das ist auch nicht besser. Deshalb musst du den Speicher entweder kopieren oder etwas Dynamisches zurückgeben.
Wenn es reicht, nur eine "Instanz" der Rückgabe zu haben, kann man auch noch die Adresse einer static-Variable zurückgeben, weil die ihren Wert behält.
-
Nexus schrieb:
Nein, aber so gibst du einen Zeiger auf ein lokales Objekt zurück, das ist auch nicht besser. Deshalb musst du den Speicher entweder kopieren oder etwas Dynamisches zurückgeben.
warum so umständlich? einfach einen zeiger auf den speicher übergeben, der befüllt werden soll:
void FPGetDateString (char *buff, size_t length) { ... snprintf (buff, length, ....); ... }
^^ damit kannste z.b. den 'DateString' direkt irgendwo einsetzen ohne irgendwelche kopierorgien, beispiel
char buff[100]; size_t lenght; ... strcpy (buff, "heute ist: "); lenght = strlen (buff); FPGetDateString (buff+lenght, sizeof(buff)-lenght); ...
Th69 schrieb:
Wenn du jedoch C++ programmieren willst, so solltest du die Klassen std::string (statt char*) sowie std::stringstream (statt sprintf) einsetzen...
'stringstream' ist im vergleich zu 's(n)printf' ziemlich umständlich zu benutzen. ich schätze, so mancher c++-jünger würde auch lieber aus gründen der einfachheit zu s(n)printf greifen.