2014-04-26 19 views
9

Như chúng ta đều biết, strcpy_s là một phiên bản an toàn của strcpy.Strcpy_s hoạt động như thế nào?

Nhưng tôi tự hỏi nó hoạt động như thế nào ...

hãy xem một số ví dụ. khai

strpy_s của:
strcpy_s errno_t (_CHAR * _DEST, size_t _SIZE, const _CHAR * _SRC)

eg1

char dest[5]; 
char* src = "abcdefg"; 
strcpy_s(dest,5,src); 

Nó sẽ trả về một sự khẳng định.
Tôi nghĩ rằng tôi có thể hiểu được điều này, sử dụng _SIZE để đảm bảo chúng tôi không thể sao chép nhân vật hơn _SIZE

Nhưng .. Tôi không thể hiểu được điều này:

char dest[5]; 
char* src = "abcdefg"; 
strcpy_s(dest,10,src); 

chúng ta có thể vẫn nhận được một xác nhận, làm thế nào điều đó đã xảy ra?

ps, ​​lỗi là:

gỡ lỗi Assertion Không
biểu: (L "Buffer là quá nhỏ" & & 0)


Trong VS2013

sẽ strcpy_s kiểm tra kích thước của dest bên trong cơ thể của nó? và nếu nó đúng thì sao? làm thế nào để kiểm tra một con trỏ như _DEST?

+0

Đọc kỹ tài liệu: [MSDN] (http://msdn.microsoft.com/en-us/library/td1esda9.aspx) – Jens

+0

Ví dụ thứ hai của bạn sai. Tham số _SIZE phải cung cấp chính xác kích thước của bộ đệm. Nếu bạn đưa ra 10 cho _SIZE nhưng bộ đệm của bạn chỉ là 5, thì kết quả là không xác định. Không có cách nào strcpy_s có thể bắt lỗi này. – Brandin

+0

thực sự đã có một khẳng định. – Joey

Trả lời

8

Đây thực sự là như thế nào để có được kích thước của một mảng chồng lúc chạy mà không mục nát nó vào một con trỏ:

template<typename T, size_t N> 
size_t arrSize(T (&array)[N]) 
{ 
    return N; 
} 

Bạn gửi nó như là một mẫu tham khảo, và cơ chế mẫu deduces kích thước. Vì vậy, bạn có thể làm điều gì đó như

int myArray[10]; 
cout << arrSize(myArray); // will display 10 

Vì vậy, tôi đoán là đây là cách "an toàn" MS strcpy_s là kiểm tra kích cỡ. Ngược lại, nếu bạn vượt qua chỉ là một con trỏ, có NO cách TIÊU CHUẨN tuân thủ trong nhận kích thước.

+0

điểm tốt! Tôi không quen thuộc với C++, nghĩ rằng tôi cần phải có một số thời gian trên mẫu trong C + + :) cảm ơn! – Joey

1

dest không thể chứa nhiều hơn 5 ký tự, đó là lý do bạn gặp lỗi. Nó không phải vì _SIZE. Nếu destchar* thì bạn cần phải chắc chắn rằng bạn phân bổ đủ bộ nhớ cho nó, bạn sẽ không nhận được bất kỳ lỗi biên dịch nào. Nhưng trong chương trình dest của bạn có kích thước cố định và strcpy_s, không giống như strcpy, hãy kiểm tra kích thước của bộ đệm đích (nếu có thể và trong trường hợp này, kích thước của nó được xác định tại thời gian biên dịch). đọc này

http://www.cplusplus.com/forum/beginner/118771/

Về cơ bản strcpy_s là phiên bản "an toàn" của strcpy, nó không cho phép bạn tràn. Từ tiêu chuẩn: C (2011) và ISO/IEC WDTR 24731 - strcpy_s: một biến thể của strcpy kiểm tra kích thước bộ đệm đích trước khi sao chép. Nội bộ, có thể là strcpy_s khẳng định sizeof(dest)<SIZE.

+0

cách kiểm tra kích thước bộ đệm đích? – Joey

+0

với 'sizeof', tôi chỉ chỉnh sửa bình luận của tôi :) Nhưng nó sẽ chỉ làm việc cho các mảng được xác định tĩnh, không cho con trỏ, mà trình biên dịch không biết bao nhiêu bộ nhớ (nếu có) bạn đã phân bổ. – vsoftco

+0

vì vậy chúng tôi không thể có được kích thước của dest? – Joey

1

MSDN Says "Bản sao strcpy_s chức năng các nội dung trong các địa chỉ của strSource, bao gồm các ký tự null chấm dứt, đến vị trí đó là theo quy định của strDestination. Chuỗi đích phải đủ lớn để giữ chuỗi nguồn và chấm dứt của nó ký tự null Hành vi của strcpy_s không xác định nếu chuỗi nguồn và đích trùng lặp."

+0

vì vậy nó không phải là "an toàn"? – Joey

+0

Định nghĩa của bạn về an toàn là gì? –

+0

khi chúng ta thử sử dụng hàm này như strcpy_s (dest, 10, src); chúng tôi sẽ nhận được ngoại lệ hoặc sẽ không làm gì cả – Joey

1

Ở chế độ DEBUG, API MicroSoft lấp đầy bộ đệm bằng 0xfd, do đó, chúng có thể kiểm tra tình trạng tràn.

Chức năng này không cắt xén chuỗi đã sao chép, nhưng tăng ngoại lệ!

Nó luôn luôn là một nỗi đau để xác định kích thước của bộ đệm đích (sử dụng _countof chứ không phải là sizeof), chủ yếu là khi bạn sử dụng một con trỏ!

Tôi có nhiều vấn đề hơn với các API "_s" đó so với các API chuẩn !!

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