sprintf_s
-
Hallo
Diese Funktion ist nicht aus dem C/C++ Standard, sondern ist von Microsoft und damit nur im Visual Studio enthalten.
Aber warum solltest du es auch benutzen? In C++ gibt es elegantere Möglichkeiten, von der VCL ganz zu schweigen.bis bald
akari
-
ich habe eine DLL die fast nur WinAPI Funktionen nutzt und möchte diese mit Borland und mit Visual Studio Compilieren können.
und im VS bringt der bei sprintf oder strcpy immer ne Warnung das die Funktion unsicher wäre.
Wegen den Libs damit ich eine VS und eine Borland lib hab.
MfG
-
Die Warnung ist nicht tragisch, die kannst du ruhig ignorieren. Du kannst die auch abschalten (_CRT_SECURE_NO_WARNINGS definieren).
-
Hallo
Destiniy schrieb:
ich habe eine DLL die fast nur WinAPI Funktionen nutzt und möchte diese mit Borland und mit Visual Studio Compilieren können.
Du könntest diese DLL intern in C++ schreiben (std:string, std::stringstream), die WinAPI-Funktionen so benutzen das du möglichst wenig eigene reservierte Speicherbereiche brauchst (C-Strings für Rpckgaben) und zur externen Benutzung ein reines C-Interface anbieten. Das gibt dir sowohl die Portabilität als auch intern den Komfort und die Sicherheit von C++.
und im VS bringt der bei sprintf oder strcpy immer ne Warnung das die Funktion unsicher wäre.
Die Warnung ist soweit korrekt das solche C-Funktionen mit Ellipsen eben nicht typsicher sind. Dafür sind in C++ ja auch eigentlich eigene Sprachkonstrukte auf Basis von Templates gedacht (std::stringstream).
Wegen den Libs damit ich eine VS und eine Borland lib hab.
Na wenn du die DLL statisch linkst dann verlierst du ja einen Teil der eigentlichen Portabilität. Denn du must ja für jeden Compiler die DLL jeweils neu kompilieren. Wäre es nicht besser du linkst dynamisch gegen ein reines C-Interface, dann kannst ein Kompilat für alle Kompiler benutzen.
bis bald
akari
-
ich habe ein reines C interface leider kann ich die Borland lib trotzdem nicht in VS benutzen
-
Hallo
Ja weil du lib (vermutlich) statisch linkst. Nur wenn die reine DLL dynamisch linkst, so das du keine lib brauchst, dann ist die DLL wirklich portabel.
bis bald
akari
-
heißt dann das ich die Dll dann nur mit Laodlibrary und getprocaddress in beiden verwenden kann?
oder entsteht da trotzdem noch ne lib nur damit ich das getprocadress nicht machen muß
MfG
-
Hallo
Die (compilerabhängige) Lib entspeht normalerweise immer beim Compileren der DLL. Entscheidend ist wie du aus deinem Programm heraus die DLL linkst. Mit der Lib kannst du statisch linken, brauchst kein GetProcAdress. Ohne Lib kannst du nur dynamisch linken und brauchst GetProcAdress.
bis bald
akari
-
Über die Sicherheit von sprintf() und desgleichen scheinen einige Unklarheiten vorzuliegen.
Bei den Format-String-Funktionen gibt es zwei Arten der Gefährdung:
- Buffer overflow. Betroffen sind sprintf(), swprintf() sowie sämtliche *scanf()-Varianten. Beispiel:
#include <cstdio> void foo (const char* arg) { char buf[200]; // Korrumpiert den Stack, wenn strlen (arg) > 192. std::sprintf (buf, "arg: '%s'", arg); // Korrumpiert den Stack, wenn der Benutzer mehr als 200 Zeichen eingibt. std::scanf ("%s\n", buf); }
- Format string attack. Betroffen sind alle C-Funktionen, die mit Format-Strings arbeiten. Ein paar eher harmlosere Beispiele:
int bar (const char* arg) { char buf[200]; wchar_t wbuf[200]; int i; // Die Funktion erwartet zwei Parameter, erhält aber nur einen. // *(int*)arg wird als erstes Argument betrachtet, die Rücksprungadresse // als String-Zeiger. Die Bandbreite möglicher Resultate rangiert zwischen // einem undefinierten Inhalt von buf, einem Buffer overflow und // einer AV. std::sprintf ("%*s", buf, arg); // Die Sicherheit ist trügerisch: die Funktion erwartet const wchar_t*, // erhält aber const char*. Ein wchar_t* muß mit zwei Null-Bytes // terminiert werden, die in einem char*-String nicht unbedingt vorkommen // müssen. Auch hier undefinierter Inhalt bis AV. if (std::strlen (arg) < 200) std::swprintf ("%s", wbuf, arg); // Erwartet zwei Parameter, erhält aber nur einen. Da die Funktion versucht, // in die Rücksprungadresse zu schreiben, mit ziemlicher Sicherheit eine AV. std::sscanf (buf, "%*d", &i); }
sprintf_s beugt nur dem ersten Problem vor, aber nicht eben optimal: wenn der Puffer zu klein ist, wird der resultierende String abgeschnitten. Die beste Alternative wäre eine kleine Hilfsfunktion wie diese:
#include <string> #include <cstdarg> #pragma hdrstop std::string str_printf (const char* format, ...) { std::va_list args; std::string retval; va_start (args, format); retval.resize (std::vsnprintf (0, 0, format, args)); std::vsnprintf (&retval[0], retval.size () + 1, format, args); va_end (args); return retval; }
Das ändert aber nichts an der Anfälligkeit für Format string attacks. Der GCC ist AFAIK in der Lage, statisch angegebene Format-Strings zu überprüfen, aber sobald man diese lokalisiert und daher zur Laufzeit lädt, dürfte das nicht mehr funktionieren. (Falls doch, so korrigiere man mich bitte.) Es ist aber möglich, mit einem gewissen Aufwand auch Format string attacks mit C++-Sprachmitteln vorzubeugen; zurzeit entwerfe ich eine Lösung für den C++Builder.
akari schrieb:
Die Warnung ist soweit korrekt das solche C-Funktionen mit Ellipsen eben nicht typsicher sind. Dafür sind in C++ ja auch eigentlich eigene Sprachkonstrukte auf Basis von Templates gedacht (std::stringstream).
Leider ist das durchaus kein adäquater Ersatz. Lokalisiere mal einen mit Stringstreams formatierten String.
boost.format wäre eine bessere Alternative.
akari schrieb:
Na wenn du die DLL statisch linkst dann verlierst du ja einen Teil der eigentlichen Portabilität.
?
Es schränkt die Portabilität doch nicht ein, wenn man statisch gegen eine DLL linkt. Wie könnten sonst C++Builder-Programme die Betriebssystem-DLLs statisch referenzieren?Wenn du dein DLL-Interface auf C-Mechanismen beschränkst, die Funktionsnamen ohne Dekoration (als extern "C") exportierst und ggf. den präfizierten Unterstrich deaktivierst, solltest du sie auch in einem Visual C++-Programm statisch linken können. Lediglich die Importbibliothek kann der BCC dir nicht generieren; für diesen Zweck erkundige dich am besten, ob so etwas wie IMPLIB auch für VC existiert.
-
Hallo
Sorry das hab ich wohl mit DLLs mit C++ Interface durcheinander gebracht. Bei denen sind die DLLs nicht portabel und müßen fürs statische Linken jeweils neu kompiliert werden.
bis bald
akari