2011-12-26 30 views
5

Điều gì xảy ra trong nội bộ khi một hàm sử dụng varargs được gọi? Là các đối số tự lưu trữ trên heap hoặc trên stack giống như bất kỳ đối số khác. Nếu trên ngăn xếp, nó hoạt động như thế nào?Danh sách đối số chiều dài thay đổi được triển khai như thế nào?

+1

Câu trả lời ngắn: phụ thuộc vào việc triển khai. Bạn thường có thể có được một ý tưởng về những gì đang xảy ra bằng cách đọc các macro trong các tệp bao gồm. stdarg.h là hình thức "hiện đại" này, varargs.h có phiên bản cũ hơn, không dùng nữa. Vì bạn đã nói cụ thể varargs, hãy thử đọc varargs.h. –

+0

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow3.html tham khảo trang web này –

Trả lời

1

Trong C, các đối số chức năng đều được đẩy lên và kéo ra khỏi ngăn xếp bằng chức năng người gọi. Chức năng người gọi biết có bao nhiêu mục được đẩy và do đó nó cũng có thể kéo chúng trở lại sau cuộc gọi. Callee chỉ có thể phỏng đoán số đối số từ các tham số khác, như chuỗi định dạng printf().

Trong Pascal, ví dụ, các đối số trên ngăn xếp được kéo bởi callee. Vì callee không nhận thức được số lượng các mục được đẩy, nó không thể khôi phục ngăn xếp về trạng thái trước đó của nó. Đó là lý do tại sao nó không thể thực hiện varargs trong Pascal.

+0

"Trong C, các đối số chức năng đều được đẩy lên và kéo ra khỏi ngăn xếp bằng chức năng của người gọi." - Điều này phụ thuộc vào việc triển khai thực hiện. –

+0

@OliCharlesworth Đúng vậy. Tôi giả định C được cấu hình để sử dụng quy ước gọi là "cdecl'," được sử dụng bởi nhiều hệ thống C cho kiến ​​trúc x86. "(Http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) –

+1

Ngoài ra, tôi muốn hãy tưởng tượng Pascal * có thể * đã có varargs, nếu nó là thông minh về nó --- bạn có thể cung cấp số đối số như đối số đầu tiên, ví dụ (và/hoặc chồng trên). Bạn sẽ phải cẩn thận trong việc thực hiện, tất nhiên, nhưng nó có thể được doable. –

8

Phụ thuộc vào triển khai thực hiện. Nhưng hầu hết có lẽ, các arg được đặt trên ngăn xếp, một sau khi khác (sau khi chương trình khuyến mãi đối số mặc định đã được thực hiện).

va_start, va_arg v.v. hoạt động đơn giản bằng cách di chuyển con trỏ qua ngăn xếp và diễn giải lại các bit như bất kỳ loại nào bạn yêu cầu.

+0

Ngắn và ngọt. +1 – cnicutar

5

Giống như đã được lưu ý trước đây, phụ thuộc vào việc triển khai.

Trong quy ước gọi C (còn gọi là cdecl), đối số được đẩy vào ngăn xếp theo thứ tự ngược, vì vậy:

void myfunc(int one, int two, int three) 

sẽ trông như thế này trên stack sau khi nó được gọi là (stack mọc lên, về phía 0):

.    .    0x00000000 
    .    . 
    .    . 
    | current frame | 
    |----------------| 
    | return address | 
    |----------------|     ^
    | one   |     | stack 
    |----------------|     | growth 
    | two   |     | direction 
    |----------------|     | 
    | three  | 
    |----------------| 
    | previous frame | 
     ...  
     ...      0xFFFFFFFF 

vì vậy, đối số đầu tiên có thể được lấy đầu tiên (vì chúng ta đều biết đó là vị trí, nó chỉ là trước khi địa chỉ trả lại), và hy vọng nó có chứa đầy đủ thông tin trên có bao nhiêu đối số khác có mặt. Ví dụ, trong printf(3) và các hàm liên quan, tất cả thông tin về các đối số khác đều có trong chuỗi định dạng, là đối số đầu tiên.

+0

"Lên trên" trong biểu đồ của bạn, nhưng "xuống dưới" theo số. –

+0

Oli, ngăn xếp có thể phát triển theo bất kỳ hướng nào. – Vovanium

+0

Có, mục đích của bình luận "hướng lên trên" là đưa cho chồng một hướng. Cá nhân, tuy nhiên, tôi thấy dễ dàng hơn để nghĩ về một chồng như một Tháp Hà Nội loại điều. – cha0site

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