簡體   English   中英

為什么 GCC 不會在長 arguments 上給我堆棧錯誤?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM