strcpy_s, strcat_s - Probleme bei mehrfacher Nutzung
-
Hallo,
ich bin heute auf ein Problem gestoßen, als ich den Code zum Laden einer Datei schreiben wollte. Im Grunde soll der Dateiname aus mehreren verschiedenen Strings zusammengesetzt werden, die ich mit strcpy_s und strcat_s zusammenfüge. Folgendermaßen sieht das bei mir aus:char line[255]; char brickDirectory[] = "bricks/"; char brickFileExtension[] = ".pcx"; char directory[255]; [...] file.getline(line, 255); [...] strcpy_s(directory, sizeof(brickDirectory), brickDirectory); strcat_s(directory, sizeof(line), line); strcat_s(directory, sizeof(brickFileExtension), brickFileExtension);
Die Initialisierungen hab ich mal dazugeschrieben, auch wenn ich mir nicht sicher bin, ob sie eine Rolle spielen, denn ich habe es auch mit anderen getestet.
Sobald ich dieses Programm ausführe, gibt mir Visual C++ an den entsprechenden Stellen "Debug Assertion Failed!" aus.
File: f:\dd\vctools\crt_bld\self_x86\crt\src\tcscat_s.inl
Linie: 32
Expression: (L"String is not null terminated" && 0)Bzw. ohne Debugmodus stürzt das Programm einfach so ab...
Woran liegt das? Wenn ich strcat_s nur einmal ausführe (also erst strcpy_s und dann strcat_s bei den oben stehenden Zeilen), funktioniert alles tadellos. Erst wenn ich an den durch strcpy_s und strcat_s entstandenen String NOCHMAL mit strcat_s etwas anhängen will, meckert er herum.
Ich würde mich freuen, wenn jemand bei diesem Problem den Fehler findet.
Gruß
-
willst du C oder C++ programmieren?
-
Kannst du mir sagen, was dagegen spricht,
std::string
zu verwenden?
-
http://msdn.microsoft.com/en-us/library/d45bbxx4(VS.80).aspx
numberOfElements
Size of the destination string buffer.Muss also wie folgt aussehen:
strcpy_s(directory, sizeof(directory), brickDirectory);
strcat_s(directory, sizeof(directory), line);
strcat_s(directory, sizeof(directory), brickFileExtension);oder sogar noch viel viel besser:
std::string directory; //... directory.append( brickDirectory ); directory.append( line ); directory.append( brickFileExtension );
-
Toll, vielen Dank.
Habe es nun mit Strings gelöst und es funktioniert ausgezeichnet. Vielen Dank für eure Hilfe.
-
rean schrieb:
http://msdn.microsoft.com/en-us/library/d45bbxx4(VS.80).aspx
numberOfElements
Size of the destination string buffer.Muss also wie folgt aussehen:
strcpy_s(directory, sizeof(directory), brickDirectory);
strcat_s(directory, sizeof(directory), line);
strcat_s(directory, sizeof(directory), brickFileExtension);In dem Fall (directory ist ein Array) muss man garkein sizeof() angeben, da strcpy_s und strcat_s template overloads genau dafür haben (damit man die grösse eines Arrays eben nicht angeben muss).
-
@ hustbaer
Und wie wird das intern gelöst?
Über defines? *würg*
-
rean schrieb:
Und wie wird das intern gelöst?
Über defines? *würg*
Ja, auch. Aber diese Makros stehen intern für Templates. Und das *würg* ist hierbei durchaus angebracht, betrachte man die beiden Stellen, die ich in MSVC++ für die Implementierung gefunden habe:
#if __STDC_WANT_SECURE_LIB__ _Check_return_wat_ _CRTIMP_ALTERNATIVE errno_t __cdecl strcpy_s(_Out_z_cap_(_SizeInBytes) char * _Dst, _In_ rsize_t _SizeInBytes, _In_z_ const char * _Src); #endif
__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(errno_t, strcpy_s, _Deref_post_z_ char, _Dest, _In_z_ const char *, _Source) __DEFINE_CPP_OVERLOAD_STANDARD_FUNC_0_1(char *, __RETURN_POLICY_DST, __EMPTY_DECLSPEC, strcpy, _Pre_cap_for_(_Source) _Post_z_, char, _Dest, _In_z_ const char *, _Source)
Und eines der Makros ist folgendermassen definiert:
#define __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_1(_ReturnType, _FuncName, _DstType, _Dst, _TType1, _TArg1) \ extern "C++" \ { \ template <size_t _Size> \ inline \ _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size], _TType1 _TArg1) \ { \ return _FuncName(_Dst, _Size, _TArg1); \ } \ }
Also alles andere als schön...
-
Die Defines werden nur verwendet um den Code kleiner zu bekommen, bzw. einen Haufen Duplizierung zu vermeiden.
Wenn man sowas selbst braucht geht das z.B. einfach so:template <size_t N> void foo(int (&a)[N]) { // ... }
Das *würg* daran ist eher die etwas un-intuitive Schreibweise "int (&a)[N]".