Yığın bellek kullanılmadığında neden ayrılıyor?


14

Aşağıdaki örneği düşünün:

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

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

İçin oluşturulan montaj kodu vector::empty(optimizasyon ile clang tarafından):

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

Neden yığın alanı ayırıyor? Hiç kullanılmaz. pushVe popihmal edilebilir. Optimize edilmiş MSVC ve gcc yapıları da bu işlev için yığın alanını kullanır ( godbolt'a bakın ), bu yüzden bir neden olmalı.


7
Örtük thisparametreyi açıkladınız mı?
dan04

1
@Bob__: Hayır. Neden yapayım? vector::size(), satır içi olmadığını simüle etmek için örnekte tanımlanmamıştır.
Dr Gut

1
Peki, bir derleyici bilmediği bir şeyi nasıl optimize edebilir?
Bob__

1
@Bob__: Bence, uygulamasını bilmek vector::size()bir yığın çerçeve ayırmak ya da ayırmak için uygun değildir vector::empty(). İçinde empty()sadece ne olursa olsun denir.
Dr Gut

1
Şey, bir şey döndüren bir işlev çağırıyorsunuz, bunun için alana ihtiyacınız var (daha iyi bilmiyorsanız).
Bob__

Yanıtlar:


11

Yığın alanı ayırır, böylece yığın 16 bayt hizalıdır. İade adresi 8 bayt aldığından gereklidir, bu nedenle yığının 16 baytını hizalı tutmak için 8 baytlık ek bir alan gerekir.

Yığın çerçevelerinin hizalanması bazı derleyiciler için komut satırı bağımsız değişkenleriyle yapılandırılabilir.

  • MSVC : Belgeler yığının her zaman 16 bayt hizalı olduğunu söylüyor. Hiçbir komut satırı argümanı bunu değiştiremez. Godbolt örneği, rspişlevin başlangıcında 40 baytın çıkarıldığını gösterir , bu da başka bir şeyin bunu da etkilediği anlamına gelir.
  • clang : -mstack-alignmentSeçenek, yığın hizalamasını belirtir. Belgelenmemesine rağmen varsayılanın 16 olduğu görülmektedir. 8 olarak ayarlarsanız, yığın ayırma ( pushve pop) oluşturulan derleme kodundan kaybolur.
  • gcc : -mpreferred-stack-boundarySeçenek, yığın hizalamasını belirtir. Verilen değer N ise, 2 ^ N bayt hizalama anlamına gelir. Varsayılan değer 4'tür, bu da 16 bayt anlamına gelir. 3 (yani 8 bayt) olarak ayarlarsanız, yığın ayırma ( subve addfor rsp) oluşturulan derleme kodundan kaybolur.

Üzerinde göz atın Godbolt .


Bu yüzden c ++ guruları, uzmanlar her zaman uyarıyorlardı: yapı / sınıf üyelerini en uzun / en büyük boyuta en küçük sıraya koyun ... sadece bu şekilde doğru verimli olurdu
nonock

@geza: Teşekkür ederim. Diğer iki derleyici için biraz araştırma yaptım ve cevabınıza yazdım. Sevdin mi?
Dr Gut

1
@ Dr.Gut: teşekkürler, cevabı çok daha iyi ve eksiksiz yaptınız. Yığın hizalamasının genellikle sistem için ABI'de belgelendiğine dikkat edin (örneğin, bazı sistemler için şu belgeler şunlardır: github.com/hjl-tools/x86-psABI/wiki/X86-psABI ).
geza

@geza: Teşekkür ederim.
Dr Gut
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.