ทำไมกองเติบโตขึ้น


31

ฉันสมมติว่ามีประวัติ แต่ทำไมสแต็คถึงลง?

ดูเหมือนว่าฉันชอบบัฟเฟอร์ล้นจะยากมากที่จะใช้ประโยชน์หากกองเติบโตขึ้น ...


3
stackoverflow.com/questions/1677415/…โปรดทราบว่าสแต็กสามารถเติบโตได้ทั้งสองทางในระดับหนึ่ง
JB King

6
มีคำถามเช่นเดียวกับคำถามนี้: stackoverflow.com/questions/2035568/… . ความจริงแล้วมีคำถามและคำตอบที่ดีกว่านี้ที่นี่: stackoverflow.com/questions/664744/…
Karlson

คำถามที่เชื่อมโยงไม่ครอบคลุมปัญหาการล้นของบัฟเฟอร์
deadalnix

1
เพราะกองขึ้นไปสูง
tylerl

2
ตำแหน่งหน่วยความจำ 0 อยู่ที่ด้านบนหรือด้านล่างหรือไม่

คำตอบ:


21

ฉันเชื่อว่ามันมาจากยุคแรก ๆ ของการคำนวณเมื่อหน่วยความจำมี จำกัด และไม่ควรจัดสรรหน่วยความจำขนาดใหญ่ไว้ล่วงหน้าเพื่อการใช้งานสแต็กโดยเฉพาะ ดังนั้นโดยการจัดสรรหน่วยความจำฮีปจากที่อยู่ศูนย์ขึ้นไปและสแต็คหน่วยความจำจากจุดสิ้นสุดของหน่วยความจำด้านล่างคุณอาจมีทั้งฮีปและสแต็คแชร์พื้นที่หน่วยความจำเดียวกัน

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

ย้อนกลับไปในสมัยนั้นไม่มี interwebz ดังนั้นจึงไม่มีปัญหาเรื่องการบุกรุกช่องโหว่ของบัฟเฟอร์ (หรืออย่างน้อยก็ในกรณีที่ interwebz มีอยู่ทั้งหมดอยู่ในระบบรักษาความปลอดภัยขั้นสูงของกระทรวงกลาโหมสหรัฐดังนั้นความเป็นไปได้ของข้อมูลที่เป็นอันตรายไม่จำเป็นต้องได้รับการพิจารณามาก)

หลังจากนั้นด้วยสถาปัตยกรรมส่วนใหญ่มันเป็นเรื่องของการรักษาความเข้ากันได้กับสถาปัตยกรรมรุ่นก่อนหน้า นั่นเป็นเหตุผลที่วันนี้สแตคดาวน์ยังคงอยู่กับเรา


8
ย้อนกลับไปอีกในประวัติศาสตร์และไม่มีกองแม้กระทั่งทุกวันนี้คอนโทรลเลอร์ไมโครคอนโทรลเลอร์ขนาด 8 และ 16 บิตจำนวนมากไม่มีฮีป สแต็กขยายตัวลงเพื่อให้สามารถติดตั้งโปรแกรมในที่อยู่หน่วยความจำเหลือน้อยและสแต็กเป็นหน่วยความจำที่เหลืออยู่ การเริ่มต้นสแต็กสามารถทำได้ก่อนที่โปรแกรมจะโหลด
mattnz

1
ไมโครคอนโทรลเลอร์ขนาดเล็กส่วนใหญ่มีฮีปไม่ใช่ฮีปที่เติบโตขึ้น เป็นการยากที่จะพิสูจน์ว่าใช้การจัดสรรหน่วยความจำแบบไดนามิกบนฮีปเมื่อคุณมี RAM ขนาดเล็ก (<1Kbytes) เพื่อใช้งาน โดยปกติขนาดหน่วยความจำเท่านั้นที่เปลี่ยนเป็นสแต็ก
tehnyit

7

หน่วยความจำโปรแกรมถูกตั้งค่าตามธรรมเนียมแล้ว

code
constants
heap (growing up)
...
stack (growing down)

สามารถแลกเปลี่ยนฮีปและสแต็กได้

แต่บัฟเฟอร์โอเวอร์โฟลว์ยังสามารถใช้ประโยชน์ได้หากสแต็กไปทางอื่น

strcpyยกตัวอย่างคลาสสิก

foo(char* in){
char[100] buff;
strcpy(buff,in);
}

กับหน่วยความจำสแต็คเป็น

ret foo
arg in
buff array
ret strcpy
buf pointer
in

นี่หมายความว่าเมื่อการคัดลอกเสร็จสิ้นที่อยู่ผู้ส่งstrcpyจะอยู่หลังบัฟเฟอร์ (แทนที่จะfooเป็นที่อยู่ผู้ส่ง) และสามารถเขียนทับได้โดยสิ่งใดก็ตามที่อยู่ในin


4

ฮาร์ดแวร์บางตัวมีฮีปเริ่มต้นที่หน่วยความจำสูงการเติบโตในขณะที่สแต็กเริ่มที่หน่วยความจำต่ำที่เติบโตขึ้น

ฮาร์ดแวร์ PA-RISC ของ HP และอื่น ๆ ทำสิ่งนี้: http://www.embeddedrelated.com/usenet/embedded/show/68749-1.php

ระบบปฏิบัติการ Multics ที่น่าเชื่อถือวิ่งบนฮาร์ดแวร์ที่มี (หนึ่งในหลาย ๆ อาจ) เติบโตขึ้นมา: ดูhttp://www.acsac.org/2002/papers/classic-multics.pdf , ตอนท้ายของส่วน 2.3.2:

ประการที่สามกองการประมวลผล Multics เติบโตในทิศทางบวกมากกว่าทิศทางลบ นี่หมายความว่าหากคุณทำบัฟเฟอร์ล้นอย่างแท้จริงคุณจะเขียนทับสแต็กเฟรมที่ไม่ได้ใช้แทนตัวชี้คืนของคุณเองทำให้การหาประโยชน์ทำได้ยากขึ้น

นั่นเป็นคำที่ค่อนข้างน่าสนใจ การบัฟเฟอร์ล้นนั้นเป็นปัญหาใหญ่เพียงอย่างเดียวเนื่องจากการจัดเรียงแบบ ยิ่งไปกว่านั้นชื่อเสียงของ Multics ในฐานะ Totally Invulnerable นั้นเป็นเพียงแค่การออกแบบฮาร์ดแวร์


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