ขีด จำกัด ของสแต็ก


10

เมื่อเร็ว ๆ นี้ฉันได้ทดสอบขีด จำกัด ของสแต็คบนอุปกรณ์สามตัวที่มีระบบปฏิบัติการแตกต่างกัน (โดย จำกัด ฉันหมายถึงจำนวนสูงสุดของระดับที่สแต็กสามารถมีได้) และฉันสังเกตเห็นว่าทุกครั้งที่ฉันกดระดับ 2 ^ 16 ข้อผิดพลาดมากเกินไปและเมื่อฉันใส่ 2 ^ 16-1 มันทำงานได้อย่างถูกต้อง

ดังนั้นคำถามของฉันคือ - จริงหรือ? สแต็กมีขีด จำกัด สูงสุด 2 ^ 16-1 ตามคำจำกัดความหรือขึ้นอยู่กับระบบปฏิบัติการ?


5
here i mean by limit the maximum number of levels that can the stack haveระดับคืออะไร?
tkausl


3
คุณทดสอบมันยังไง? คุณใช้ 2-byte (dword) เป็นอินพุตหรือไม่?
pro3carp3

6
คุณใช้ภาษาโปรแกรมภาษาใด ข้อ จำกัด ที่คมชัดที่จำนวนคงที่บ่งบอกว่าเป็นข้อ จำกัด โดยเจตนาของรันไทม์เฉพาะภาษาของคุณและไม่ได้ตามขนาดสแต็คที่ระบบปฏิบัติการจัดสรร ยกตัวอย่างเช่นงูหลามดูเหมือนว่าจะบังคับใช้วงเงิน 1000 โดยเริ่มต้นที่จะป้องกันไม่ให้คุณจากการตีกองล้นจริง (การกู้คืนจากกองล้นจริงเป็นเรื่องยาก)
CodesInChaos

คำตอบ:


20

เป็นระบบปฏิบัติการที่เจาะจงอย่างยิ่ง (& เฉพาะคอมพิวเตอร์) และในบาง OS คุณมีวิธีกำหนดค่า (และเพิ่มขึ้น) ขีด จำกัด มันเป็นคอมไพเลอร์ที่เฉพาะเจาะจง (หรือภาษาโปรแกรมของคุณ - เฉพาะการใช้งาน) เนื่องจากคอมไพเลอร์บางตัว (รวมถึงGCCล่าสุดสำหรับรหัส C บางประเภทที่จำกัด ) สามารถเพิ่มประสิทธิภาพการโทรบางส่วน ได้

(ข้อมูลจำเพาะภาษาการเขียนโปรแกรมบางอย่างจำเป็นต้องใช้การปรับแต่ง tail call เช่นR5RS )

ฉันไม่แน่ใจว่าคำถามของคุณจะทำให้ความรู้สึก (และไม่แน่นอนของคุณ 2 16จำนวน จำกัด ) บนเดสก์ท็อป Linux ของฉัน (Debian / Sid / x86-64, Linux เคอร์เนล 4.9, 32Gb RAM, Intel i5-4690S) ฉันอาจมีสแตกการโทรสูงถึง 8 เมกะไบต์ (และฉันสามารถเพิ่มขีด จำกัด นั้นได้ถ้าฉันต้องการ )

Multi-threadingและASLRจะทำให้คำถามของคุณที่ซับซ้อนมากขึ้น ดูเช่นpthread_attr_setstack (3) อ่านยังเกี่ยวกับกองแยก (มักใช้โดยไปใช้งาน) และเกี่ยวกับความต่อเนื่องสไตล์ผ่าน ดูคำตอบนี้ด้วย

สำหรับสิ่งที่มีค่าฉันแค่ลองใช้รหัส C99 (และ C11) ต่อไปนี้:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void recfun(int x, int d) {
  printf("start recfun x=%d d=%d\n", x, d);
  fflush(NULL);
  if (d>0)
    recfun(x+1, d-1);
  printf("end recfun x=%d d=%d\n", x, d);
}

int main(int argc, char**argv) {
  int md = argc>1?atoi(argv[1]):10000;
  printf ("start md=%d\n", md);
  recfun(0, md);
  printf("end md=%d clock=%ld µs\n", md, clock());
}    
// eof recur.c

และฉันก็สามารถเรียกใช้recurโปรแกรมนั้น(คอมไพล์ด้วย GCC 6 เป็นgcc -Wall -O recur.c -o recur) เป็นrecur 161000 (มากเกินขีด จำกัด2 16ของคุณ) ด้วยrecur 256000มันยังทำงาน เมื่อrecur 456000เกิดข้อผิดพลาด (ด้วยสแต็กล้นสำหรับระดับx=272057) ฉันไม่มีความอดทนสำหรับการทดสอบอื่น ๆ ลองบนคอมพิวเตอร์ของคุณ อย่าลืมขอการปรับให้เหมาะสม

กฎง่ายๆ (สำหรับเดสก์ท็อปแล็ปท็อปแท็บเล็ต) อาจทำให้สายการโทรของคุณต่ำกว่าหนึ่งเมกะไบต์

โดยผ่านยัง-fstack-usage จะ gccฉันได้รับต่อไปนี้recur.suไฟล์ (ตัวเลขอยู่ในไบต์สอดคล้องกับ 8Mb สแต็คสัญชาตญาณขีด จำกัด ของข้าพเจ้าอย่าลืมmainกรอบโทรและที่สำคัญกว่ารูปแบบสแต็คเริ่มต้นติดตั้งโดย kernel เมื่อทำexecve (2 ) ... สำหรับcrt0 ):

 recur.c:5:10:recfun    32  static
 recur.c:13:9:main  16  static

PS Arduino ของฉันมีAtmega328 ที่มี RAM เพียง 2Kbytes ดังนั้นแน่นอนว่ามันไม่สามารถเกิดขึ้นได้อีกมากมาย ฉันเดาว่ามีเฟรมสแต็คเพียงไม่กี่ร้อยอันเท่านั้นที่สามารถทำได้ใน Arduinos


3

ขนาดสแต็กสำหรับเธรดหลักของกระบวนการ Windows ถูกตั้งค่าโดยตัวลิงก์ ค่าเริ่มต้นคือ 1MB แต่สามารถปรับได้ด้วยสวิตช์ / STACK เธรดที่สร้างในภายหลังสามารถใช้พารามิเตอร์ dwStackSize ของฟังก์ชัน CreateThread

ดังนั้น .. ถ้าคุณกำลังทดสอบระบบปฏิบัติการ Windows ต่างๆพวกเขาทั้งหมดมีขนาดสแต็คเริ่มต้นเท่ากันตั้งแต่ NT4.0 เป็นอย่างน้อย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.