2012-11-07 28 views
6

Tôi sẽ thông qua một mã số được viết trước đây và tôi thấy StringCbPrintf() chức năngStringCbprintf là gì và khác nhau như thế nào so với sprintf chung?

tôi thấy lời tuyên bố trên trang web msdn như thế này:

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

_in__out_ ở đây là gì?

Và tại sao cần thiết khi chúng tôi đã có sprintf()?

+0

Đã thêm thẻ "windows" và "winapi", vì câu hỏi này liên quan đến chú thích SAL, đặc biệt là Windows. –

+0

Lưu ý rằng '_in_' và' _out_' không phải là SAL hợp lệ (chúng là '_In_' và' _Out_', với ký tự viết hoa ban đầu). Một SAL hợp lệ thay thế là với dấu gạch dưới kép hàng đầu (và chữ cái viết hoa ban đầu): '__in' và' __out'. –

Trả lời

8

_In__Out_ (lưu ý: không _in_/_out _ như bạn đã viết, cũng không __In__/__Out__ với dấu gạch đôi, như được viết trong một số câu trả lời khác) đều được cái gọi là SAL Chú thích. Chúng có thể được sử dụng với tùy chọn biên dịch /analyze và có thể giúp xác định các lỗi và sự cố như tràn bộ đệm, v.v. với bộ đệm C và con trỏ C thô. Ngoài số MSDN documentation on SAL, bạn cũng có thể đọc số này blog post.

Có người mỉa mai (và sai) viết rằng:

"Trong phần còn lại của thế giới, đầu vào là con trỏ const nhưng tôi đoán rằng là quá đơn giản :)."

thiếu thực tế rằng SAL là mạnh hơn hơn thế. Trong thực tế, với SAL bạn cũng có thể chỉ định kích thước tối đa của một bộ đệm đích, chỉ ra tham số nào chứa kích thước bộ đệm đích; ví dụ. nếu bạn mở <strsafe.h> tiêu đề, bạn có thể đọc mà các chú thích SAL thực tế sử dụng cho StringCbPrintfW (phiên bản Unicode của StringCbPrintf) là một cái gì đó như thế:

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

Lưu ý cách chú thích __out_bcount(cbDest) SAL áp dụng cho các tham số pszDest xác định rằng đây là một con trỏ đến một đầu ra đệm (__out), mà kích thước được thể hiện theo byte (_bcount) bởi tham số cbDest. Như bạn thấy, đây là một chú thích phong phú (phong phú hơn đơn giản "const" hoặc "không const"). Theo tôi, SAL là loại vô ích nếu bạn viết mã C++ với các lớp chứa mạnh như std::vector hoặc std::string, có kích thước riêng của chúng, v.v. Nhưng SAL có thể hữu ích trong mã C-ish với các con trỏ thô (như một số API Win32).

Về phần thứ hai của câu hỏi của bạn:

"Tại sao chúng ta cần StringCbPrintf nếu chúng ta đã có sprintf"

nguyên nhân chủ yếu là sprintf là một không an toàn và đệm overruns- chức năng dễ bị; thay vào đó với StringCbPrintf, bạn phải chỉ định kích thước tối đa của bộ đệm đích và điều này có thể giúp ngăn ngừa tràn bộ đệm (là kẻ thù bảo mật).

2

The documentation cố gắng giải thích điều đó cho bạn:

So với các chức năng nó thay thế, StringCbPrintf cung cấp xử lý bổ sung cho đệm thích hợp xử lý trong mã của bạn. Xử lý bộ đệm kém có liên quan đến nhiều vấn đề bảo mật liên quan đến việc tràn bộ đệm. StringCbPrintf luôn vô hiệu hóa một bộ đệm đích không đồng bộ.

Bộ trang trí __In____Out__ được sử dụng trong Microsoft API: s để biểu thị cách đối số con trỏ được sử dụng. Ở phần còn lại của thế giới, đầu vào là const con trỏ nhưng tôi đoán đó là quá đơn giản. :)

+0

Nice ..Nó có nghĩa là '__in__' có nghĩa là' const' và '__out__' cho bộ đệm đầu ra. Nhưng tại sao nó lại cần thiết? chúng ta có sprintf phải không? – Omkant

+0

+1 cho __in__ và __out__, tôi đã nghĩ một loại tham số ràng buộc như chúng ta có trong hàm cơ sở dữ liệu – Omkant

+0

Lưu ý rằng '__In__' và' __Out__' là sai: SAL hợp lệ là '__in/__ out' (như được chỉ định [ở đây] (http://msdn.microsoft.com/en-us/library/ms235402(v=vs.80).aspx)) hoặc '_In _/_ Out_' (như được chỉ định [ở đây] (http://msdn.microsoft. com/vi-us/library/ms235402 (v = vs.100) .aspx)). Hơn nữa, -1 vì SAL là _richer_ so với độ chính xác 'const' đơn giản. –

2

Như người ta nói here:

StringCbPrintf là một thay thế cho các chức năng sau:

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

Vì vậy, nó không chỉ thay thế sprintf, mà còn có thể làm việc với wchar chẳng hạn. Nó cũng giới thiệu thêm bộ đệm xử lý để ngăn chặn tràn bộ đệm (như đã nêu trong cùng một bài báo msdn). Nó cũng luôn luôn vô hiệu hóa bộ đệm đích. _in__out_ ở đó để hiển thị cho bạn thông số nào là thông số đầu vào và là thông số đầu ra. Đó là những khả năng nhất là #define d là không có gì, và biến mất trước khi bắt đầu biên dịch.

+0

tốt dòng này đã được viết bằng msdn nhưng vấn đề là với __in__ và __out__ .. anyway +1 – Omkant

+0

@Omkant, trong nhiều sách bạn có thể đọc trên C++, các tác giả thực sự khuyên bạn nên phân biệt đối số đầu vào và đầu ra hàm. Một giải pháp đang sử dụng các macro như vậy, ví dụ: '#define IN' và' #define OUT'.Chúng hiển thị rõ ràng loại đối số, và biến mất trước khi quá trình biên dịch bắt đầu. Tôi không khuyến khích bạn làm điều đó, đó chỉ là một số thông tin bổ sung: P – SingerOfTheFall

+0

cảm ơn tôi đã hiểu – Omkant

Các vấn đề liên quan