ขนาดสแต็กสูงสุดของโปรแกรม C / C ++


115

ฉันต้องการทำ DFS บนอาร์เรย์ 100 X 100 (พูดว่าองค์ประกอบของอาร์เรย์แสดงถึงโหนดกราฟ) ดังนั้นสมมติว่ากรณีที่เลวร้ายที่สุดความลึกของการเรียกฟังก์ชันแบบเรียกซ้ำอาจสูงถึง 10,000 โดยการเรียกแต่ละครั้งใช้เวลาไม่เกิน 20 ไบต์ ดังนั้นจึงเป็นไปได้ว่ามีความเป็นไปได้ที่จะเกิด stackoverflow หรือไม่?

ขนาดสูงสุดของสแต็กใน C / C ++ คืออะไร?

โปรดระบุสำหรับ gcc สำหรับทั้ง
1) cygwin บน Windows
2) Unix

ข้อ จำกัด ทั่วไปคืออะไร?


11
คุณรู้ไหมว่าคุณสามารถใช้การค้นหาเชิงลึกก่อนโดยไม่ต้องเรียกซ้ำได้ใช่ไหม
Sebastian

4
ไม่ฉันไม่รู้โปรดอธิบาย
avd

1
ฉันได้สร้างตัวอย่างเล็ก ๆ ของ DFS โดยไม่มีการเรียกซ้ำในคำตอบของฉัน
Andreas Brinck

56
บวกหนึ่งคำถามเกี่ยวกับสแต็กล้นจริง
Sam Watkins

3
@SamWatkins ใช่ปัญหาใหญ่ที่สุดอย่างหนึ่งสำหรับฉันที่มีชื่อว่า Stack Overflow คือฉันอาจค้นหา "stack overflow" ใน Google และลงเอยในเว็บไซต์นี้ แต่ไม่จำเป็น / มีโอกาสน้อยในคำถามเกี่ยวกับ stack overflow ...
lalilulelost

คำตอบ:


106

ใน Visual Studio ขนาดสแต็กเริ่มต้นคือ 1 MB ฉันคิดว่าดังนั้นด้วยความลึกของการเรียกซ้ำ 10,000 แต่ละเฟรมสแต็กอาจมีขนาดไม่เกิน 100 ไบต์ซึ่งควรเพียงพอสำหรับอัลกอริทึม DFS

คอมไพเลอร์ส่วนใหญ่รวมถึง Visual Studio ช่วยให้คุณสามารถระบุขนาดสแต็กได้ ใน linux บางตัว (ทั้งหมด?) รสชาติขนาดสแต็กไม่ได้เป็นส่วนหนึ่งของไฟล์ปฏิบัติการ แต่เป็นตัวแปรสภาพแวดล้อมในระบบปฏิบัติการ จากนั้นคุณสามารถตรวจสอบขนาดของสแต็คที่มีและตั้งค่าให้ค่าใหม่ด้วยตัวอย่างเช่นulimit -sulimit -s 16384

นี่คือลิงค์ที่มีขนาดสแต็กเริ่มต้นสำหรับ gcc

DFS โดยไม่ต้องเรียกซ้ำ:

std::stack<Node> dfs;
dfs.push(start);
do {
    Node top = dfs.top();
    if (top is what we are looking for) {
       break;
    }
    dfs.pop();
    for (outgoing nodes from top) {
        dfs.push(outgoing node);
    }
} while (!dfs.empty())

12
และสำหรับการอ้างอิง BFS จะเหมือนกันยกเว้นว่าคุณใช้ FIFO แทนสแต็ก
Steve Jessop

ใช่หรือใน STL-lingo ใช้ std :: deque กับ pop_front / push_back
Andreas Brinck

DFS ของคุณพร้อมผลลัพธ์สแต็กจะแตกต่างจากเวอร์ชันการเรียกซ้ำ ในบางกรณีมันไม่สำคัญ แต่ในบางกรณี (เช่นในการเรียงลำดับโทโพโลยี) คุณจะได้ผลลัพธ์ที่ไม่ถูกต้อง
spin_eight

ใช่ขีด จำกัด เริ่มต้นสำหรับ VS คือ 1MB ข้อมูลเพิ่มเติมและวิธีการตั้งค่าอื่นสามารถพบได้ในเอกสารของ Microsoft: msdn.microsoft.com/en-us/library/tdkhxaks(v=vs.140).aspx
FrankS101

ฉันชอบใช้โครงสร้างข้อมูลสแต็คที่ชัดเจนสำหรับอัลกอริทึมดังกล่าวมากกว่าการเรียกซ้ำเพื่อที่ 1. ไม่ขึ้นอยู่กับขนาดของสแต็กของระบบ 2. สามารถเปลี่ยนอัลกอริทึมเพื่อใช้โครงสร้างข้อมูลอื่นเช่นคิวหรือลำดับความสำคัญโดยไม่ต้องโยน รหัสทั้งหมด
Sam Watkins

47

สแต็กสำหรับเธรดมักมีขนาดเล็กกว่า คุณสามารถเปลี่ยนค่าเริ่มต้นในเวลาลิงก์หรือเปลี่ยนในเวลาทำงานก็ได้เช่นกัน สำหรับการอ้างอิงค่าเริ่มต้นบางประการคือ:

  • glibc i386, x86_64 7.4 MB
  • Tru64 5.1 5.2 ลบ
  • Cygwin 1.8 ลบ
  • โซลาริส 7..10 1 ลบ
  • MacOS X 10.5 460 KB
  • AIX 5 98 KB
  • OpenBSD 4.0 64 KB
  • HP-UX 11 16 KB

14
กำหนดเชิงประจักษ์โดย Bruno Haible lists.gnu.org/archive/html/bug-coreutils/2009-10/msg00262.html
pixelbeat

17

ขึ้นอยู่กับแพลตฟอร์มขึ้นอยู่กับ toolchain ขึ้นอยู่กับ ulimit ขึ้นอยู่กับพารามิเตอร์ .... ไม่ได้ระบุไว้เลยและมีคุณสมบัติคงที่และไดนามิกมากมายที่สามารถมีอิทธิพลต่อมัน


4
ไม่มี "ขีด จำกัด ทั่วไป" บน Windows ที่มีตัวเลือก VC ++ linker เริ่มต้นและพฤติกรรม CreateThread เริ่มต้นโดยทั่วไปจะมีค่าประมาณ 1 MiB ต่อเธรด บน Linux ที่มีผู้ใช้ไม่ จำกัด ฉันเชื่อว่าโดยทั่วไปไม่มีขีด จำกัด (สแต็กสามารถขยายลงมาเพื่อใช้พื้นที่ที่อยู่เกือบทั้งหมด) โดยพื้นฐานแล้วหากคุณต้องถามคุณไม่ควรใช้สแตก
DrPizza

1
ในระบบฝังตัวคุณอาจมี 4k หรือน้อยกว่า ในกรณีนี้คุณต้องถามถึงแม้จะสมเหตุสมผลที่จะใช้สแต็ก คำตอบมักจะเป็น Gallic ยัก
Steve Jessop

1
จริงอยู่บ่อยครั้งในโหมดเคอร์เนล
DrPizza

6

ใช่มีความเป็นไปได้ที่สแต็กล้น มาตรฐาน C และ C ++ ไม่ได้กำหนดสิ่งต่างๆเช่นความลึกของสแต็กซึ่งโดยทั่วไปเป็นปัญหาด้านสิ่งแวดล้อม

สภาพแวดล้อมการพัฒนาและ / หรือระบบปฏิบัติการที่เหมาะสมที่สุดจะช่วยให้คุณสามารถปรับแต่งขนาดสแต็กของกระบวนการได้ทั้งที่ลิงค์หรือเวลาโหลด

คุณควรระบุระบบปฏิบัติการและสภาพแวดล้อมการพัฒนาที่คุณกำลังใช้สำหรับความช่วยเหลือที่ตรงเป้าหมายมากขึ้น

ตัวอย่างเช่นภายใต้ Ubuntu Karmic Koala ค่าเริ่มต้นสำหรับ gcc คือสงวนไว้ 2M และกำหนด 4K แต่สามารถเปลี่ยนแปลงได้เมื่อคุณเชื่อมโยงโปรแกรม ใช้--stackตัวเลือกในldการทำเช่นนั้น


2
@lex: ไม่มีข้อ จำกัด ทั่วไป ขึ้นอยู่กับพารามิเตอร์จำนวนมาก
Michael Foukarakis

@paxdiablo: ความหมายของสงวนและมุ่งมั่นคืออะไร?
avd

2
การสงวนไว้คือพื้นที่ที่อยู่ที่จะจัดสรรความมุ่งมั่นคือเท่าใดในการแนบพื้นที่เก็บข้อมูลสำรอง กล่าวอีกนัยหนึ่งการสำรองพื้นที่ที่อยู่ไม่ได้หมายความว่าหน่วยความจำจะอยู่ที่นั่นเมื่อคุณต้องการ หากคุณไม่เคยใช้สแต็กมากกว่า 4K คุณจะไม่เสียหน่วยความจำจริงไปอีก 1.6M หากคุณต้องการรับประกันว่าจะมีสแต็กเพียงพอที่สงวนไว้และการผูกมัดควรเหมือนกัน
paxdiablo

3
@paxdiablo 2M - 4k ไม่ใช่ 1.6M แค่พูด. (ทำให้ฉันสับสนใน 3 ครั้งแรกที่ฉันอ่านความคิดเห็นของคุณ)
griffin

2
@griffin ความรุ่งโรจน์สำหรับคนแรกที่จับได้ใน 3 ปีขึ้นไป แน่นอนฉันหมายถึง "ส่วนที่เหลือ" - ฉันจะหลีกเลี่ยงร่างที่แท้จริงเพื่อไม่ให้เกิดความผิดพลาดอีก :-)
paxdiablo

5

ฉันเพิ่งหมดสแต็คในที่ทำงานมันเป็นฐานข้อมูลและกำลังเรียกใช้เธรดบางส่วนโดยพื้นฐานแล้วนักพัฒนาก่อนหน้านี้ได้โยนอาร์เรย์ขนาดใหญ่บนสแต็กและสแต็กก็ต่ำ ซอฟต์แวร์นี้รวบรวมโดยใช้ Microsoft Visual Studio 2015

แม้ว่าเธรดจะหมดสแต็ก แต่เธรดก็ล้มเหลวและดำเนินต่อไปอย่างเงียบ ๆ แต่สแต็กล้นเมื่อเข้าถึงเนื้อหาของข้อมูลบนสแต็กเท่านั้น

คำแนะนำที่ดีที่สุดที่ฉันสามารถให้ได้คืออย่าประกาศอาร์เรย์บนสแต็กโดยเฉพาะอย่างยิ่งในแอปพลิเคชันที่ซับซ้อนและโดยเฉพาะอย่างยิ่งในเธรดให้ใช้ฮีปแทน นั่นคือสิ่งที่มีไว้สำหรับ;)

นอกจากนี้โปรดทราบว่าอาจไม่ล้มเหลวทันทีเมื่อประกาศสแต็ก แต่เฉพาะในการเข้าถึงเท่านั้น ฉันเดาว่าคอมไพลเลอร์ประกาศสแต็กภายใต้หน้าต่าง "ในแง่ดี" กล่าวคือจะถือว่าสแต็กได้รับการประกาศและมีขนาดเพียงพอจนกว่าจะใช้งานได้แล้วพบว่าไม่มีสแต็กอยู่ที่นั่น

ระบบปฏิบัติการที่แตกต่างกันอาจมีนโยบายการประกาศสแตกต่างกัน โปรดแสดงความคิดเห็นหากคุณทราบว่านโยบายเหล่านี้คืออะไร


3

ฉันไม่แน่ใจว่าคุณหมายถึงอะไรเมื่อทำการค้นหาในเชิงลึกก่อนในอาร์เรย์สี่เหลี่ยม แต่ฉันคิดว่าคุณรู้ว่าคุณกำลังทำอะไรอยู่

หากขีด จำกัด ของสแต็กเป็นปัญหาคุณควรจะสามารถแปลงโซลูชันแบบวนซ้ำของคุณเป็นโซลูชันแบบวนซ้ำที่ผลักค่ากลางไปยังสแตกซึ่งได้รับการจัดสรรจากฮีป

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