Jelaskan konsep bingkai tumpukan secara singkat

200

Tampaknya saya mendapatkan ide panggilan stack dalam desain bahasa pemrograman. Tapi saya tidak dapat menemukan (mungkin, saya hanya tidak mencari cukup keras) penjelasan yang layak apa stack frame adalah.

Jadi saya ingin meminta seseorang untuk menjelaskannya kepada saya dalam beberapa kata.

ikostia
sumber

Jawaban:

195

Bingkai tumpukan adalah bingkai data yang didorong ke tumpukan. Dalam kasus tumpukan panggilan, bingkai tumpukan akan mewakili panggilan fungsi dan data argumennya.

Jika saya ingat dengan benar, fungsi alamat pengirim didorong ke stack terlebih dahulu, kemudian argumen dan ruang untuk variabel lokal. Bersama-sama, mereka membuat "bingkai," meskipun ini mungkin tergantung arsitektur. Prosesor tahu berapa byte dalam setiap frame dan menggerakkan penunjuk tumpukan sesuai dengan bingkai didorong dan muncul dari tumpukan.

EDIT:

Ada perbedaan besar antara tumpukan panggilan tingkat tinggi dan tumpukan panggilan prosesor.

Ketika kita berbicara tentang tumpukan panggilan prosesor, kita berbicara tentang bekerja dengan alamat dan nilai pada tingkat byte / kata dalam perakitan atau kode mesin. Ada "tumpukan panggilan" ketika berbicara tentang bahasa tingkat yang lebih tinggi, tetapi mereka adalah alat debugging / runtime yang dikelola oleh lingkungan runtime sehingga Anda dapat mencatat apa yang salah dengan program Anda (pada tingkat tinggi). Pada level ini, hal-hal seperti nomor baris dan metode dan nama kelas sering dikenal. Pada saat prosesor mendapatkan kode, sama sekali tidak memiliki konsep tentang hal-hal ini.

Tony R
sumber
6
"Prosesor tahu berapa byte dalam setiap frame dan menggerakkan penunjuk tumpukan sesuai dengan bingkai didorong dan muncul dari tumpukan." - Saya ragu prosesor tahu apa-apa tentang tumpukan, karena KAMI memanipulasinya melalui subbing (alokasi), mendorong dan muncul. Dan inilah konvensi pemanggilan yang menjelaskan bagaimana kita harus menggunakan stack.
Victor Polevoy
78

Jika Anda memahami tumpukan dengan sangat baik maka Anda akan memahami bagaimana memori bekerja dalam program dan jika Anda memahami bagaimana memori bekerja dalam program Anda akan memahami bagaimana fungsi menyimpan dalam program dan jika Anda memahami bagaimana fungsi menyimpan dalam program Anda akan memahami bagaimana fungsi rekursif bekerja dan jika Anda memahami bagaimana fungsi rekursif bekerja, Anda akan memahami cara kerja kompiler dan jika Anda memahami bagaimana kompiler bekerja, pikiran Anda akan berfungsi sebagai kompiler dan Anda akan men-debug program apa pun dengan sangat mudah

Biarkan saya menjelaskan cara kerja tumpukan:

Pertama, Anda harus tahu bagaimana fungsi direpresentasikan dalam stack:

Heap menyimpan nilai yang dialokasikan secara dinamis.
Stack menyimpan nilai alokasi dan penghapusan otomatis.

masukkan deskripsi gambar di sini

Mari kita pahami dengan contoh:

def hello(x):
    if x==1:
        return "op"
    else:
        u=1
        e=12
        s=hello(x-1)
        e+=1
        print(s)
        print(x)
        u+=1
    return e

hello(4)

Sekarang pahami bagian dari program ini:

masukkan deskripsi gambar di sini

Sekarang mari kita lihat apa itu stack dan apa itu stack parts:

masukkan deskripsi gambar di sini

Alokasi tumpukan:

Ingat satu hal: jika kondisi pengembalian fungsi apa pun terpenuhi, tidak peduli itu telah memuat variabel lokal atau tidak, itu akan segera kembali dari tumpukan dengan bingkai tumpukan itu. Ini berarti bahwa setiap fungsi rekursif mendapatkan kondisi basis terpenuhi dan kami mengembalikan setelah kondisi dasar, kondisi basis tidak akan menunggu untuk memuat variabel lokal yang terletak di bagian "lain" dari program. Ini akan segera mengembalikan frame saat ini dari tumpukan yang mengikuti frame berikutnya sekarang dalam catatan aktivasi.

Lihat ini dalam praktik:

masukkan deskripsi gambar di sini

Deallokasi blok:

Jadi sekarang setiap kali suatu fungsi menemukan pernyataan kembali, itu menghapus bingkai saat ini dari tumpukan.

Saat kembali dari tumpukan, nilai-nilai akan dikembalikan secara terbalik dari urutan aslinya di mana mereka dialokasikan dalam tumpukan.

masukkan deskripsi gambar di sini

Aaditya Ura
sumber
3
tumpukan tumbuh ke bawah dan tumpukan tumbuh ke atas, Anda memilikinya terbalik di diagram Anda. DIAGRAM YANG BENAR DI SINI
Rafael
@ Rafael maaf atas kebingungan, saya sedang berbicara tentang Arah pertumbuhan saya tidak berbicara tentang arah pertumbuhan tumpukan. Ada perbedaan antara arah pertumbuhan dan arah pertumbuhan tumpukan. Lihat Di Sini stackoverflow.com/questions/1677415/…
Aaditya Ura
2
Rafael benar. Juga gambar pertama salah. Ganti dengan yang lain (cari gambar google untuk "tumpukan tumpukan").
Nikos
Jadi jika saya mengerti dengan benar, pada diagram ketiga Anda, ada 3 stack frame karena hello()secara rekursif disebut hello()yang kemudian (lagi) dipanggil secara rekursif hello(), dan frame global adalah fungsi asli yang disebut pertama hello()?
Andy J
1
Di mana tautannya membawa kita ?? Sebagai masalah serius keamanan, tautan ini harus dihapus sesegera mungkin.
Shivanshu
45

Pembungkus cepat. Mungkin seseorang memiliki penjelasan yang lebih baik.

Stack panggilan terdiri dari 1 atau beberapa frame stack. Setiap bingkai tumpukan berhubungan dengan panggilan ke fungsi atau prosedur yang belum diakhiri dengan pengembalian.

Untuk menggunakan frame stack, sebuah thread menyimpan dua pointer, satu disebut Pointer Pointer (SP), dan yang lainnya disebut Frame Pointer (FP). SP selalu menunjuk ke "atas" dari tumpukan, dan FP selalu menunjuk ke "atas" dari frame. Selain itu, utas juga mengelola program counter (PC) yang menunjuk ke instruksi selanjutnya yang akan dieksekusi.

Berikut ini disimpan di stack: variabel lokal dan temporer, parameter aktual dari instruksi saat ini (prosedur, fungsi, dll.)

Ada beberapa konvensi panggilan berbeda mengenai pembersihan tumpukan.

ervinbosenbacher
sumber
7
Jangan lupa bahwa alamat pengirim subroutine ada di tumpukan.
Tony R
4
Frame Pointer juga adalah Base Pointer dalam istilah x86
peterchaula
1
Saya ingin menekankan bahwa penunjuk bingkai menunjuk ke awal bingkai tumpukan untuk inkarnasi prosedur yang sedang aktif.
Server Khalilov
13

"Tumpukan panggilan terdiri dari bingkai tumpukan ..." -  Wikipedia

Frame tumpukan adalah benda yang Anda letakkan di tumpukan. Mereka adalah struktur data yang berisi informasi tentang subrutin untuk dipanggil.

Waleed Khan
sumber
Maaf, saya tidak tahu bagaimana saya melewatkan ini di wiki. Terima kasih. Apakah saya mengerti dengan benar, bahwa dalam bahasa dinamis ukuran bingkai bukan nilai konstan karena fungsi lokal tidak diketahui dengan pasti?
ikostia
Ukuran dan sifat bingkai sangat bergantung pada arsitektur alat berat. Bahkan, paradigma panggilan stack sangat spesifik untuk arsitektur. Sejauh yang saya tahu itu selalu variabel karena panggilan fungsi yang berbeda akan memiliki jumlah data argumen yang berbeda.
Tony R
Perhatikan bahwa ukuran bingkai tumpukan harus diketahui oleh prosesor saat sedang dimanipulasi. Ketika ini terjadi, ukuran data sudah ditentukan. Bahasa dinamis dikompilasi ke kode mesin seperti bahasa statis, tetapi sering dilakukan tepat waktu sehingga kompiler dapat mempertahankan dinamisme dan prosesor dapat bekerja dengan ukuran bingkai "dikenal". Jangan bingung bahasa tingkat yang lebih tinggi dengan kode mesin / perakitan, di mana hal ini sebenarnya terjadi.
Tony R
Yah, tapi bahasa dinamis juga memiliki tumpukan panggilan mereka, bukan? Maksud saya, jika, katakanlah, Python ingin menjalankan beberapa prosedur, data tentang prosedur ini disimpan di dalam struktur beberapa juru bahasa Python, apakah saya benar? Jadi saya maksudkan bahwa tumpukan panggilan hadir tidak hanya pada level rendah.
ikostia
Setelah membaca sedikit artikel wikipedia itu, saya berdiri terkoreksi (sedikit). Ukuran frame stack dapat tetap tidak diketahui pada waktu kompilasi . Tetapi pada saat prosesor bekerja dengan stack + frame pointer, ia harus mengetahui ukurannya. Ukurannya bisa variabel tetapi prosesor tahu ukurannya, itulah yang ingin saya katakan.
Tony R
5

Pemrogram mungkin memiliki pertanyaan tentang susunan bingkai bukan dalam istilah luas (bahwa itu adalah entitas menghanguskan dalam tumpukan yang hanya melayani satu panggilan fungsi dan menyimpan alamat pengirim, argumen dan variabel lokal) tetapi dalam arti yang sempit - ketika istilah stack framestersebut disebutkan dalam konteks opsi kompiler.

Apakah penulis pertanyaan bermaksud atau tidak, tetapi konsep bingkai tumpukan dari aspek opsi kompiler adalah masalah yang sangat penting, tidak dicakup oleh balasan lain di sini.

Sebagai contoh, kompiler Microsoft Visual Studio 2015 C / C ++ memiliki opsi berikut yang berkaitan dengan stack frames:

  • / Oy (Penghilangan Frame-Pointer)

GCC memiliki yang berikut:

  • -fomit-frame-pointer (Jangan simpan frame pointer dalam register untuk fungsi yang tidak membutuhkannya. Ini menghindari instruksi untuk menyimpan, mengatur dan mengembalikan frame pointer; itu juga membuat register tambahan tersedia di banyak fungsi )

Intel C ++ Compiler memiliki yang berikut:

  • -fomit-frame-pointer (Menentukan apakah EBP digunakan sebagai register tujuan umum dalam optimasi)

yang memiliki alias berikut:

  • / Oy

Delphi memiliki opsi baris perintah berikut:

  • - $ W + (Generate Stack Frames)

Dalam arti tertentu, dari perspektif kompiler, bingkai tumpukan hanyalah kode masuk dan keluar untuk rutin , yang mendorong jangkar ke tumpukan - yang juga dapat digunakan untuk debugging dan untuk penanganan pengecualian. Alat debugging dapat memindai data tumpukan dan menggunakan jangkar ini untuk penelusuran balik, saat mencari call sitesdi tumpukan, yaitu untuk menampilkan nama fungsi dalam urutan yang disebut hierarki. Untuk arsitektur Intel, itu push ebp; mov ebp, espatau enteruntuk masuk danmov esp, ebp; pop ebp atauleave untuk keluar.

Itu sebabnya sangat penting untuk memahami bagi seorang programmer apa itu stack frame ketika datang ke opsi kompiler - karena kompiler dapat mengontrol apakah akan menghasilkan kode ini atau tidak.

Dalam beberapa kasus, frame tumpukan (kode masuk dan keluar untuk rutin) dapat dihilangkan oleh kompiler, dan variabel akan langsung diakses melalui penunjuk tumpukan (SP / ESP / RSP) daripada penunjuk basis yang nyaman (BP / ESP / RSP). Ketentuan untuk penghilangan bingkai tumpukan, misalnya:

  • fungsi adalah fungsi daun (yaitu entitas akhir yang tidak memanggil fungsi lain);
  • tidak ada coba / akhirnya atau coba / kecuali atau konstruksi serupa, yaitu tidak ada pengecualian yang digunakan;
  • tidak ada rutin yang dipanggil dengan parameter keluar pada stack;
  • fungsi tidak memiliki parameter;
  • fungsi tidak memiliki kode rakitan inline;
  • dll ...

Menghilangkan frame stack (entri dan kode keluar untuk rutin) dapat membuat kode lebih kecil dan lebih cepat, tetapi juga dapat secara negatif mempengaruhi kemampuan debuggers untuk melacak kembali data dalam stack dan untuk menampilkannya ke programmer. Ini adalah opsi kompiler yang menentukan di bawah kondisi mana suatu fungsi harus memiliki kode masuk dan keluar, misalnya: (a) selalu, (b) tidak pernah, (c) saat diperlukan (menentukan kondisi).

Maxim Masiutin
sumber
-1

Stack frame adalah informasi yang dikemas terkait dengan panggilan fungsi. Informasi ini umumnya termasuk argumen yang diteruskan ke fungsi, variabel lokal dan tempat untuk kembali setelah penghentian. Catatan aktivasi adalah nama lain untuk bingkai tumpukan. Tata letak bingkai tumpukan ditentukan dalam ABI oleh pabrikan dan setiap kompiler yang mendukung ISA harus memenuhi standar ini, namun skema tata letak dapat bergantung pada kompiler. Umumnya ukuran bingkai stack tidak terbatas tetapi ada konsep yang disebut "zona merah / terlindungi" untuk memungkinkan panggilan sistem ... dll untuk dieksekusi tanpa mengganggu bingkai tumpukan.

Selalu ada SP tetapi pada beberapa ABI (misalnya ARM dan PowerPC), FP bersifat opsional. Argumen yang perlu ditempatkan ke stack dapat diimbangi menggunakan SP saja. Apakah frame stack dihasilkan untuk panggilan fungsi atau tidak tergantung pada jenis dan jumlah argumen, variabel lokal dan bagaimana variabel lokal diakses secara umum. Pada sebagian besar ISA, pertama, register digunakan dan jika ada lebih banyak argumen daripada register yang didedikasikan untuk meneruskan argumen, ini ditempatkan ke stack (Misalnya x86 ABI memiliki 6 register untuk melewati argumen integer). Oleh karena itu, kadang-kadang, beberapa fungsi tidak memerlukan bingkai tumpukan untuk ditempatkan di tumpukan, hanya alamat pengirim didorong ke tumpukan.

teko mabuk
sumber