Đ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?
Trả lời
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.
"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. –
@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) –
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. –
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.
Ngắn và ngọt. +1 – cnicutar
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.
"Lên trên" trong biểu đồ của bạn, nhưng "xuống dưới" theo số. –
Oli, ngăn xếp có thể phát triển theo bất kỳ hướng nào. – Vovanium
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
- 1. Danh sách đối số mẫu có độ dài thay đổi?
- 2. Tại sao Java không sử dụng chính danh sách đối số độ dài thay đổi?
- 3. PHP - Vượt qua mảng dưới dạng danh sách đối số có độ dài thay đổi
- 4. OpenID được triển khai như thế nào?
- 5. Làm thế nào để chiều dài danh sách đếm Python
- 6. Các tham chiếu yếu được triển khai như thế nào?
- 7. Các mảng được triển khai trong java như thế nào?
- 8. HttpSession được triển khai như thế nào?
- 9. Đối số chiều dài biến PHP?
- 10. Danh sách đối số quá dài - Unix
- 11. JavaScript: Thay đổi bit theo chiều dài số dài
- 12. Python tìm chiều dài danh sách trong danh sách con
- 13. Độ dài thay đổi của danh sách đối số hàm trong Erlang
- 14. Các mảng được triển khai trong Perl như thế nào?
- 15. Thay thế đối số bằng một danh sách trong R
- 16. bash:/bin/ls: Đối số danh sách quá dài
- 17. Chiều dài của từ dài nhất trong một danh sách
- 18. Python đi qua danh sách như là đối số
- 19. "danh sách đối số thực tế hoặc chính thức khác với chiều dài"
- 20. C# Generics được triển khai như thế nào?
- 21. IO không chặn được triển khai như thế nào?
- 22. Máy tính Google được triển khai như thế nào?
- 23. Atan2 được triển khai bằng .NET như thế nào?
- 24. Danh sách liên kết được triển khai như thế nào mà không cần sử dụng con trỏ?
- 25. Haskell đã thay đổi như thế nào?
- 26. Arrays.sort (Object [] a) - được triển khai như thế nào?
- 27. Phạm vi Lexical được triển khai như thế nào?
- 28. Các mutex được triển khai như thế nào?
- 29. Làm thế nào để triển khai một danh sách `Python` liên tục?
- 30. Cách đối sánh mẫu trong Scala được triển khai ở cấp độ bytecode như thế nào?
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. –
http://www.tenouk.com/Bufferoverflowc/Bufferoverflow3.html tham khảo trang web này –