Benutzer mit den meisten Antworten
Funktion _tcscpy

Frage
-
Hallo,
ich habe bisher zwei dialogbasierende Anwendungen von VS 6.0 in VS 2005 erfolgreich übernommen. Darin sind mehrere Stellen mit strcpy, bei denen eine Warnung ausgegeben wurde. Entsprechend der Beschreibung konnte ich die Warnung bereingen, in dem ich strcpy durch strcpy_s ersetzt habe. Das hat im Debugger auch funktioniert.
Nun bin ich bei der nächsten dialogbasierende Anwendungen. Darin wird in der Zeile
_tcscpy(lpFileName,lpszFileName);
die Warnung
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
ausgegeben. Aufgrund meiner funktionierenden Änderungen habe ich auch hier _tcscpy durch _tcscpy_s ersetzt.
Leider führt das zu diesem Fehler:
error C2660: 'strcpy_s': Funktion akzeptiert keine 2 Argumente
Zwei Argumente bei strcpy_s haben aber bei den anderen dialogbasierende Anwendungen funktioniert. Die Funktion mit dem Problem ist Teil einer Klasse, die ich vor vielen Jahren heruntergeladen habe. Hier die Funktion:
BOOL CSysInfo::GetFileInfo(LPCTSTR lpszFileName, DWORD *v_major, DWORD *v_minor, DWORD *v_build, DWORD *v_something, DWORD *size) { *v_major=0; *v_minor=0; *v_build=0; *v_something=0; *size=0; if (lpszFileName==NULL) return FALSE; DWORD InfoSize; VS_FIXEDFILEINFO fileinfo; VS_FIXEDFILEINFO *fi; fi=&fileinfo; UINT size_fileinfo; size_fileinfo=sizeof(fileinfo); LPTSTR lpFileName; int i=0; i=_tcslen(lpszFileName); if (i>0) { // Convert LPCTSTR to LPTSTR lpFileName=new TCHAR[i+1]; memset(lpFileName,0,i+1); // VS60 _tcscpy(lpFileName,lpszFileName); _tcscpy_s(lpFileName,lpszFileName); // <- hier die Fehlermeldung } else return FALSE; InfoSize=GetFileVersionInfoSize(lpFileName,0); if (InfoSize>0) { LPVOID lpVoid; lpVoid=malloc(InfoSize); memset(lpVoid,0,InfoSize); if (GetFileVersionInfo(lpFileName,NULL,InfoSize,lpVoid)) { if (VerQueryValue(lpVoid,_T("\\"),(LPVOID *)&fi,&size_fileinfo)) { *v_major=((fi->dwFileVersionMS>>16) & 0x0000FFFF); *v_minor=(fi->dwFileVersionMS & 0x0000FFFF); *v_build=((fi->dwFileVersionLS>>16) & 0x0000FFFF); *v_something=(fi->dwFileVersionLS & 0x0000FFFF); }; }; free(lpVoid); delete lpFileName; } else { delete lpFileName; return FALSE; }; // Get file size WIN32_FIND_DATA fdata; HANDLE hFile; hFile=FindFirstFile(lpszFileName,&fdata); if (hFile!=INVALID_HANDLE_VALUE) { *size=fdata.nFileSizeLow; FindClose(hFile); return TRUE; } else return FALSE; }
Wie kann ich die das Problem beheben?
Danke im Voraus und viele Grüße
Bernd
Antworten
-
_tcscpy_s benötigt 3 Parameter! Quelle, Ziel, und Länge des Ziel Puffers!
Hier ein Beispiel
http://bytes.com/topic/net/answers/283115-_tcscpy_s-avoiding-buffer-overruns
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 3. März 2015 10:40
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 8. April 2015 06:59
-
Hallo Bernd,
siehe http://stackoverflow.com/questions/2946916/using-strcpy-s-for-tchar-pointer-microsoft-specific
Da es sich bei Dir um einen Dateinamen handelt, könntest Du mit MAX_PATH für den Puffer arbeiten, siehe Naming Files, Paths, and Namespaces, womit das (potentiell unsichere) _tcslen eleminiert werden kann.
Gruß Elmar
- Als Antwort markiert Bernd Föry Dienstag, 3. März 2015 10:28
-
Hallo,
auf diese Weise erhalte ich die Meldung nicht mehr und der Inhalt wird korrekt kopiert:
size_t nTest2 = _tcslen(lpszFileName);
_tcscpy_s(lpFileName,nTest2 + 1,lpszFileName);Danke nochmals an alle und viele Grüße
Bernd
- Als Antwort markiert Bernd Föry Dienstag, 3. März 2015 10:29
Alle Antworten
-
_tcscpy_s benötigt 3 Parameter! Quelle, Ziel, und Länge des Ziel Puffers!
Hier ein Beispiel
http://bytes.com/topic/net/answers/283115-_tcscpy_s-avoiding-buffer-overruns
Best regards
Bordon
Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 3. März 2015 10:40
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Mittwoch, 8. April 2015 06:59
-
Hallo Bordon,
danke für Deine Antwort.
Mit Hilfe Deiner Informationen bin ich schon etwas weiter. Das ist mein aktueller Stand:
1.) Parameter
Die Reihenfolge der Parameter für die Funktion _tcscpy_s ist (Ziel, Größe, Quelle).
Stimmt das so?
2.) Funktion _tcscpy_s
_tcscpy_s(lpFileName, sizeof(lpszFileName),lpszFileName);
Die Ermittlung der Größe mit sizeof für den zweiten Parameter ist falsch. Nach meinem Verständnis müsste ich dafür die Anzahl der Buchstaben als Größe verwenden.
Wie kann ich die Größe für den zweiten Parameter ermitteln?
Viele Grüße
Bernd
-
Hallo Bernd,
siehe http://stackoverflow.com/questions/2946916/using-strcpy-s-for-tchar-pointer-microsoft-specific
Da es sich bei Dir um einen Dateinamen handelt, könntest Du mit MAX_PATH für den Puffer arbeiten, siehe Naming Files, Paths, and Namespaces, womit das (potentiell unsichere) _tcslen eleminiert werden kann.
Gruß Elmar
- Als Antwort markiert Bernd Föry Dienstag, 3. März 2015 10:28
-
1) Ja, das stimmt, siehe auch https://msdn.microsoft.com/de-de/library/td1esda9.aspx
2) Wenn lpFileName ein schnöder Pointer ist, kannst Du das gar nicht ermitteln. Dieser zeigt erst einmal nur auf ein einziges Element. Die Information muss in diesem Fall von außen kommen. Wenn lpFileName ein Array ist, kannst Du das so machen:
TCHAR lpFileName[MAX_PATH]; size_t len;
len = (sizeof(lpFileName) / sizeof(lpFileName[0]));
// Oder noch einfacher len = _countof(lpFileName);
-
Hallo Rene,
danke für Deine Antwort.
In meinem Fall ist die Variable lpszFileName ein Parameter der Funktion (siehe Programmcode vom Beitrag oben) und zeigt auf einen TCHAR. Dadurch kann ich sizeof(lpszFileName) nicht verwenden.
Mit dieser Funktion kann ich die Anzahl der Buchstaben ermitteln:
size_t nTest2 = _tcslen(lpszFileName);
In der Zeile
_tcscpy_s(lpFileName,nTest2,lpszFileName);
erhalte ich dann aber diese Meldung:
Was ist in der oben genannten Zeile noch falsch?
Viele Grüße
Bernd
-
Hallo,
auf diese Weise erhalte ich die Meldung nicht mehr und der Inhalt wird korrekt kopiert:
size_t nTest2 = _tcslen(lpszFileName);
_tcscpy_s(lpFileName,nTest2 + 1,lpszFileName);Danke nochmals an alle und viele Grüße
Bernd
- Als Antwort markiert Bernd Föry Dienstag, 3. März 2015 10:29
-
Hallo Bernd,
auf diese Weise erhalte ich die Meldung nicht mehr und der Inhalt wird korrekt kopiert:
size_t nTest2 = _tcslen(lpszFileName);
_tcscpy_s(lpFileName,nTest2 + 1,lpszFileName);Danke nochmals an alle und viele Grüße
Da dieses Verfahren bereits im von Bordon angeführten Beispiel zu finden war, schlage ich auch Bordons Beitrag als Antwort vor. In Deinem Fall hat die Zeichenfolge i Zeichen (den Null-Terminator ausgenommen). Im oben angegebenen Beispiel hat sie (DESTLEN-1) Zeichen, daher solltest Du als zweiten Parameter nTest2 + 1 übergeben (in Hinsicht auf den Nullterminator), wie dort empfohlen wird (DESTLEN anstatt DESTLEN-1).
Gruß,
Dimitar
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.
- Bearbeitet Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 3. März 2015 10:48