2014-11-16 14 views
7

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 macro va_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 macro va_end trước khi có bất kỳ tham chiếu nào khác đến ap.

(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?

+3

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. –

+4

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ó. –

+0

@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

Trả lời

6

Bạn chỉ cần va_copy nếu bạn vẫn định 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 phải sử dụng lại ap (ngoại trừ có lẽ để chuyển nó đến va_end, nếu bạn là người tạo nó với va_start), thì bạn không cần phải va_copy nó.

+0

Tôi đã quan sát các triển khai mà một va_list hoạt động như thể được truyền theo giá trị [do đó các đối số được tiêu thụ bởi một hàm nhận nó trở lại tồn tại khi hàm đó trả về], và các hàm khác hoạt động như thể truyền qua tham chiếu [ ]. Vấn đề với việc sử dụng một va_list sau khi gọi một phương pháp mà cũng sử dụng nó là như vậy, không chỉ đơn thuần là "lý thuyết". – supercat

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