Khi mọi người nói, " strcpy()
nguy hiểm, hãy sử dụng strncpy()
thay thế" (hoặc các câu tương tự về strcat()
v.v., nhưng tôi sẽ sử dụng strcpy()
ở đây làm trọng tâm của mình), họ có nghĩa là không có giới hạn kiểm tra strcpy()
. Do đó, một chuỗi quá dài sẽ dẫn đến vượt quá bộ đệm. Họ đúng. Sử dụng strncpy()
trong trường hợp này sẽ ngăn chặn quá tải bộ đệm.
Tôi cảm thấy rằng điều đó strncpy()
thực sự không sửa được lỗi: nó giải quyết một vấn đề mà một lập trình viên giỏi có thể dễ dàng tránh được.
Là một lập trình viên C, bạn phải biết kích thước đích trước khi cố gắng sao chép chuỗi. Đó cũng là giả định trong strncpy()
và strlcpy()
của tham số cuối cùng: bạn cung cấp kích thước đó cho chúng. Bạn cũng có thể biết kích thước nguồn trước khi sao chép chuỗi. Sau đó, nếu điểm đến không đủ lớn, đừng gọistrcpy()
. Phân bổ lại bộ đệm hoặc làm điều gì đó khác.
Tại sao tôi không thích strncpy()
?
strncpy()
là một giải pháp tồi trong hầu hết các trường hợp: chuỗi của bạn sẽ bị cắt ngắn mà không có bất kỳ thông báo nào — tôi thà viết thêm mã để tự tìm hiểu điều này và sau đó thực hiện hành động mà tôi muốn thực hiện, thay vì để một số hàm quyết định tôi về những gì phải làm.
strncpy()
là rất kém hiệu quả. Nó ghi vào từng byte trong bộ đệm đích. Bạn không cần hàng ngàn cái đó '\0'
ở cuối điểm đến của mình.
- Nó không viết kết thúc
'\0'
nếu đích không đủ lớn. Vì vậy, dù thế nào bạn cũng phải tự mình làm như vậy. Sự phức tạp của việc làm này không đáng để bạn gặp rắc rối.
Bây giờ, chúng tôi đến strlcpy()
. Những thay đổi từ strncpy()
làm cho nó tốt hơn, nhưng tôi không chắc liệu hành vi cụ thể có strl*
đảm bảo sự tồn tại của chúng hay không: chúng quá cụ thể. Bạn vẫn phải biết kích thước đích. Nó hiệu quả hơn strncpy()
vì nó không nhất thiết phải ghi vào từng byte trong đích. Nhưng nó giải quyết một vấn đề có thể được giải quyết bằng cách thực hiện: *((char *)mempcpy(dst, src, n)) = 0;
.
Tôi không nghĩ rằng bất kỳ ai nói điều đó strlcpy()
hoặc strlcat()
có thể dẫn đến các vấn đề bảo mật, những gì họ (và tôi) đang nói rằng họ có thể dẫn đến lỗi, ví dụ, khi bạn mong đợi chuỗi hoàn chỉnh được viết thay vì một phần của nó.
Vấn đề chính ở đây là: cần sao chép bao nhiêu byte? Lập trình viên phải biết điều này và nếu anh ta không, strncpy()
hoặc strlcpy()
sẽ không cứu anh ta.
strlcpy()
và strlcat()
không phải là tiêu chuẩn, không phải ISO C hay POSIX. Vì vậy, việc sử dụng chúng trong các chương trình di động là không thể. Trên thực tế, strlcat()
có hai biến thể khác nhau: việc triển khai Solaris khác với những biến thể khác đối với các trường hợp cạnh liên quan đến độ dài 0. Điều này khiến nó thậm chí còn ít hữu ích hơn so với cách khác.
strlcpy
vàstrlcat
sẽ báo cáo một số loại tình trạng lỗi nếu chúng chạm vào giới hạn kích thước bộ đệm đích. Mặc dù bạn có thể kiểm tra độ dài trả về để kiểm tra điều này, nhưng nó không rõ ràng. Nhưng tôi nghĩ đó là một chỉ trích nhỏ. Lập luận 'họ khuyến khích sử dụng chuỗi C, và vì vậy chúng xấu' là ngớ ngẩn.