8 Stimmen

Was ist StringCbprintf und wie unterscheidet es sich vom allgemeinen sprintf?

Ich gehe gerade einen zuvor geschriebenen Code durch und habe die Funktion StringCbPrintf() gefunden

Ich habe die Deklaration auf der msdn-Website wie folgt gefunden :

HRESULT StringCbPrintf(
  _Out_  LPTSTR pszDest,
  _In_   size_t cbDest,
  _In_   LPCTSTR pszFormat,
  _In_    ...
);

Was bedeuten _in_ und _out_ hier ?

Und warum wird dies benötigt, wenn wir bereits sprintf() haben ?

9voto

Mr.C64 Punkte 40373

_In_ und _Out_ (Hinweis: Weder _in_/_out_ wie Sie geschrieben haben, noch __In__/__Out__ mit doppelten Unterstrichen, wie in einigen anderen Antworten geschrieben) sind sogenannte SAL-Annotationen. Sie können mit der /analyze-Compileroption verwendet werden und können dabei helfen, Fehler und Probleme wie Pufferüberläufe usw. mit Roh-C-Puffern und -Zeigern zu identifizieren. Neben der MSDN-Dokumentation zu SAL können Sie auch diesen Blogpost lesen.

Jemand hat ironischerweise (und fälschlicherweise) geschrieben:

"Im Rest der Welt sind Eingaben konstante Zeiger, aber ich nehme an, das war zu einfach. :)"

ohne die Tatsache zu beachten, dass SAL mächtiger ist als das. Tatsächlich können Sie mit SAL auch die maximale Größe eines Ziel-Puffers angeben und angeben, welcher Parameter die Größe des Ziel-Puffers enthält; zum Beispiel, wenn Sie das -Header öffnen, können Sie lesen, dass die tatsächlichen SAL-Annotationen, die für StringCbPrintfW (die Unicode-Version von StringCbPrintf) verwendet werden, ungefähr so aussehen:

STRSAFEAPI
StringCbPrintfW(
    __out_bcount(cbDest) STRSAFE_LPWSTR pszDest,
    __in size_t cbDest,
    __in __format_string STRSAFE_LPCWSTR pszFormat,
    ...)
{
    ....

Beachten Sie, wie die __out_bcount(cbDest) SAL-Annotation, die auf den Parameter pszDest angewendet wird, angibt, dass dies ein Zeiger auf einen Ausgabe-Puffer (__out) ist, dessen Größe in Bytes (_bcount) durch den Parameter cbDest ausgedrückt wird. Wie Sie sehen können, handelt es sich hier um eine umfangreiche Annotation (reichhaltiger als einfach "const" oder "nicht const").

Nach meiner Meinung ist SAL ziemlich nutzlos, wenn Sie C++-Code mit robusten Containerklassen wie std::vector oder std::string schreiben, die ihre eigene Größe kennen usw. Aber SAL kann in C-ähnlichem Code mit Rohzeigern (wie mehreren Win32-APIs) nützlich sein.

Zur zweiten Hälfte Ihrer Frage:

"Warum benötigen wir StringCbPrintf, wenn wir bereits sprintf haben?"

Der Hauptgrund dafür ist, dass sprintf eine unsichere und anfällige Funktion für Pufferüberläufe ist; stattdessen müssen Sie bei StringCbPrintf die maximale Größe des Zielpuffers angeben, und dies kann dazu beitragen, Pufferüberläufe zu verhindern (die Sicherheitsfeinde sind).

3voto

unwind Punkte 377331

Die Dokumentation versucht, das für Sie zu erklären:

Verglichen mit den Funktionen, die sie ersetzt, bietet StringCbPrintf zusätzliche Verarbeitung für die ordnungsgemäße Pufferbehandlung in Ihrem Code. Eine schlechte Pufferbehandlung wird bei vielen Sicherheitsproblemen mit Pufferüberläufen impliziert. StringCbPrintf terminiert immer einen Puffer mit einer Länge ungleich null.

Die Dekorateure __In__ und __Out__ werden in Microsoft-APIs verwendet, um anzuzeigen, wie ein Zeigerargument verwendet wird. Im Rest der Welt sind Eingaben const Zeiger, aber ich denke, das war zu einfach. :)

2voto

SingerOfTheFall Punkte 28940

Wie hier gesagt wird:

StringCbPrintf ist ein Ersatz für die folgenden Funktionen:

  • sprintf, swprintf, _stprintf
  • wsprintf
  • wnsprintf
  • _snprintf, _snwprintf, _sntprintf

Es ersetzt also nicht nur sprintf, sondern auch diese zum Arbeiten mit wchar, zum Beispiel. Es führt auch zusätzliche Pufferverarbeitung ein, um Pufferüberläufe zu verhindern (wie im selben MSDN-Artikel angegeben). Es terminiert auch immer den Ziel-Puffer mit null. _in_ und _out_ zeigen Ihnen, welche Parameter Eingabeparameter sind und welche Ausgabeparameter sind. Diese sind höchstwahrscheinlich als nichts definiert und verschwinden, bevor die Kompilierung beginnt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X