เหตุใดจึงมีการจัดสรรหน่วยความจำสแต็คเมื่อไม่ใช้


14

ลองพิจารณาตัวอย่างต่อไปนี้:

struct vector {
    int  size() const;
    bool empty() const;
};

bool vector::empty() const
{
    return size() == 0;
}

รหัสการประกอบที่สร้างขึ้นสำหรับvector::empty(โดยเสียงดังกราวด้วยการเพิ่มประสิทธิภาพ):

push    rax
call    vector::size() const
test    eax, eax
sete    al
pop     rcx
ret

ทำไมมันจัดสรรพื้นที่สแต็ค? มันไม่ได้ใช้เลย pushและpopอาจถูกมองข้าม บิลด์ที่ปรับให้เหมาะสมของ MSVC และ gcc ยังใช้พื้นที่สแต็กสำหรับฟังก์ชั่นนี้ (ดูที่godbolt ) ดังนั้นต้องมีเหตุผล


7
คุณคำนึงถึงthisพารามิเตอร์โดยนัยหรือไม่
dan04

1
@Bob__: ไม่ทำไมต้องฉัน vector::size()ไม่ได้กำหนดไว้ในตัวอย่างเพื่อจำลองว่าไม่มีการ inlined
ดร. Gut

1
ดังนั้นคอมไพเลอร์สามารถเพิ่มประสิทธิภาพสิ่งที่มันไม่รู้ได้อย่างไร
Bob__

1
@Bob__: ผมคิดว่าการเรียนรู้การดำเนินงานของไม่เกี่ยวข้องกับการจัดสรรหรือไม่จัดสรรกองกรอบสำหรับvector::size() vector::empty()ในempty()มันถูกเรียกว่าอะไรก็ตามที่มันเป็น
ดร. Gut

1
คุณกำลังเรียกฟังก์ชั่นที่ส่งคืนบางสิ่งคุณต้องการพื้นที่สำหรับสิ่งนั้น (ถ้าคุณไม่รู้อะไรเพิ่มเติม)
Bob__

คำตอบ:


11

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

การจัดตำแหน่งของเฟรมสแต็กสามารถกำหนดค่าด้วยอาร์กิวเมนต์บรรทัดคำสั่งสำหรับคอมไพเลอร์บางตัว

  • MSVC : เอกสารระบุว่าสแต็กอยู่ในแนวเดียวกัน 16 ไบต์เสมอ ไม่มีอาร์กิวเมนต์บรรทัดคำสั่งที่สามารถเปลี่ยนแปลงได้ ตัวอย่าง godbolt แสดงให้เห็นว่า 40 ไบต์ถูกลบออกจากrspจุดเริ่มต้นของฟังก์ชันซึ่งหมายความว่ามีสิ่งอื่นที่ส่งผลกระทบต่อสิ่งนี้
  • เสียงดังกราว : -mstack-alignmentตัวเลือกที่ระบุการจัดตำแหน่งสแต็ค ดูเหมือนว่าค่าเริ่มต้นคือ 16 แม้ว่าจะไม่มีเอกสารก็ตาม หากคุณตั้งค่าเป็น 8 การจัดสรรสแต็ก ( pushและpop) จะหายไปจากรหัสแอสเซมบลีที่สร้างขึ้น
  • gcc : -mpreferred-stack-boundaryตัวเลือกจะระบุการจัดเรียงสแต็ค หากค่าที่กำหนดคือ N หมายถึงการจัดตำแหน่ง 2 ^ N ไบต์ ค่าเริ่มต้นคือ 4 ซึ่งหมายถึง 16 ไบต์ หากคุณตั้งค่าเป็น 3 (เช่น 8 ไบต์) การจัดสรรสแต็ก ( subและaddสำหรับrsp) จะหายไปจากรหัสแอสเซมบลีที่สร้างขึ้น

ตรวจสอบในgodbolt


นั่นเป็นเหตุผลว่าทำไมผู้เชี่ยวชาญด้าน c ++ ผู้เชี่ยวชาญมักถูกเตือนเสมอ: ทำให้สมาชิก struct / class เรียงลำดับที่ยาวที่สุด / ใหญ่ที่สุดให้เล็กที่สุด ... ด้วยวิธีนี้เท่านั้นที่จะมีประสิทธิภาพอย่างถูกต้อง
nonock

@geza: ขอบคุณ ฉันทำการค้นคว้าบางอย่างสำหรับคอมไพเลอร์อีกสองตัวและเขียนลงในคำตอบของคุณ คุณชอบมันไหม?
ดร. Gut

1
@ Dr.Gut: ขอบคุณคุณทำให้คำตอบดีขึ้นและสมบูรณ์มากขึ้น โปรดทราบว่าการจัดเรียงสแต็กมักจะมีเอกสารใน ABI สำหรับระบบ (ตัวอย่างเช่นสำหรับบางระบบนี่คือเอกสาร: github.com/hjl-tools/x86-psABI/wiki/X86-psABI )
geza

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