This blog post tuyên bố rằng đi qua một va_list
chức năng khác giống như trong đoạn mã sau là không an toàn, và rằng va_list
trước tiên phải được sao chép sử dụng va_copy
:Có an toàn khi vượt qua va_list đến một chức năng khác mà không cần sử dụng va_copy không?
void
foo_ap(const char *fmt, va_list ap)
{
char buf[128];
vsnprintf(buf, sizeof(buf), fmt, ap);
// now, do something with buf ...
}
Giống như một trong những ý kiến cho bài viết trên blog đề cập đến, tôi có thể không thấy điều này sẽ không an toàn như thông số C99 nêu rõ (7.15):
Đối tượng
ap
có thể được chuyển làm đối số cho một chức năng khác; nếu hàm đó gọi macrova_arg
với tham sốap
, giá trịap
trong hàm gọi là không xác định và sẽ được chuyển đến macrova_end
trước khi có bất kỳ tham chiếu nào khác đếnap
.
(Chừng nào foo_ap
không tham khảo ap
sau khi đi qua nó trên, phần thứ hai của câu dường như không áp dụng anyway.) Tác giả của bài viết trên blog nói trong bình luận khác rằng ông có thể sai, nhưng có lẽ ai đó có thể thêm một số làm rõ. Tôi có thực sự phải sử dụng va_copy
để an toàn không? Hoặc có bất kỳ nền tảng nào không phù hợp với thông số kỹ thuật và yêu cầu sử dụng va_copy
không?
Bài đăng trên blog dường như mâu thuẫn trực tiếp với mệnh đề bạn trích dẫn từ tiêu chuẩn C99. Tác giả blog nói "Một thời gian dài trước đây" vào lúc bắt đầu, vì vậy tôi đoán là anh ta đang xử lý một số hệ thống cũ, không tuân thủ tiêu chuẩn. –
Bạn chỉ cần 'va_copy' nếu bạn vẫn có kế hoạch sử dụng' ap' sau khi trả về 'vsnprintf'. Ví dụ, bạn có thể muốn gọi 'vsnprintf' hai lần - một lần để xác định kích thước bộ đệm cần thiết, và một lần nữa để định dạng cho thực. Nếu bạn không cần sử dụng 'ap' một lần nữa ngoại trừ việc chuyển nó sang' va_end', thì bạn không cần phải 'va_copy' nó. –
@IgorTandetnik Nếu bạn đưa ra bình luận của bạn một câu trả lời, tôi sẽ chấp nhận nó. – nwellnhof