![](/img/trans.png)
[英]Why won't GCC give errors passing a void * to a void** parameter?
[英]Why GCC won't give me stackerror on long arguments?
我的意思是向某人展示您發送到 C function 的每個參數都被推入堆棧。 它也發生在 Ruby、Python、Lua、Z686155AF75A60A0F6E9D80C1FZEDD 等中。
所以我寫了一個 Ruby 代碼,生成一個 C 代碼:
#!/usr/bin/env ruby
str = Array.new(10, &:itself)
a = <<~EOF
#include <stdio.h>
void x(#{str.map { |x| "int n#{x}" }.join(?,)}) {
printf("%d\\n", n#{str.length - 1}) ;
}
int main() { x(#{str.join(?,)}) ; }
EOF
IO.write('p.c', a)
使用 Ruby 解釋器運行此代碼后,我得到一個名為 p.c 的文件,其中包含以下內容:
#include <stdio.h>
void x(int n0,int n1,int n2,int n3,int n4,int n5,int n6,int n7,int n8,int n9) {
printf("%d\n", n9) ;
}
int main() { x(0,1,2,3,4,5,6,7,8,9) ; }
這很好,並且編譯和執行都很好。
但是如果我給 ruby 程序一個數組大小為 100,000,它應該生成一個 C 文件,該文件需要 n0 到 n999999 arguments。 這意味着 100,000 個 arguments。
快速的谷歌搜索顯示 C 的 arguments 存儲在堆棧中。
傳遞這些 arguments 應該會給我一個堆棧錯誤,但事實並非如此。 GCC 編譯得很好,我也得到了 99999 的 output。
但是使用 Clang,我得到:
p.c:4:17: error: use of undeclared identifier 'n99999'
printf("%d\n", n99999) ;
^
p.c:8:195690: error: too many arguments to function call, expected 34464, have 100000
p.c:3:6: note: 'x' declared here
2 errors generated.
GCC 是如何處理那么多 arguments 的? 在大多數情況下,當堆棧大小為 10900 時,我會在其他編程語言上遇到堆棧錯誤。
向你的朋友證明這一點的最好方法是編寫一個無限遞歸的 function:
#include <stdio.h>
void recurse(int x) {
static int iterations=0;
printf("Iteration: %d\n", ++iterations);
recurse(x);
}
int main() {
recurse(1);
}
假設存在堆棧,這將始終溢出堆棧(並非所有架構都使用堆棧)。 它會告訴你在堆棧溢出發生之前你到達了多少堆棧幀; 這將使您了解堆棧的深度。
至於為什么gcc
編譯, gcc
不知道目標堆棧大小,因此無法檢查堆棧溢出。 理論上可以有一個足夠大的堆棧來容納 100,000 個 arguments。 那還不到半兆字節。 不知道為什么clang
表現不同; 這將取決於查看生成的 C 代碼。
如果您可以分享您正在使用的計算機系統/架構,那將會很有幫助。 您引用了適用於 64 位 Intel 系統(例如 PC/Windows)的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.