Bagaimana cara Kesalahan Segmentasi bekerja di bawah tenda?


266

Sepertinya saya tidak dapat menemukan informasi mengenai hal ini selain dari "MMU CPU mengirimkan sinyal" dan "kernel mengarahkannya ke program yang menyinggung, menghentikannya".

Saya berasumsi bahwa itu mungkin mengirim sinyal ke shell dan shell menanganinya dengan menghentikan proses yang menyinggung dan mencetak "Segmentation fault". Jadi saya menguji asumsi itu dengan menulis shell yang sangat minim yang saya sebut crsh (crap shell). Shell ini tidak melakukan apa pun kecuali mengambil input pengguna dan memasukkannya ke system()metode.

#include <stdio.h>
#include <stdlib.h>

int main(){
    char cmdbuf[1000];
    while (1){
        printf("Crap Shell> ");
        fgets(cmdbuf, 1000, stdin);
        system(cmdbuf);
    }
}

Jadi saya menjalankan shell ini di terminal telanjang (tanpa bashberjalan di bawah). Kemudian saya melanjutkan untuk menjalankan program yang menghasilkan segfault. Jika asumsi saya benar, ini akan a) crash crsh, menutup xterm, b) tidak mencetak "Segmentation fault", atau c) keduanya.

braden@system ~/code/crsh/ $ xterm -e ./crsh
Crap Shell> ./segfault
Segmentation fault
Crap Shell> [still running]

Kembali ke titik awal, kurasa. Saya baru saja menunjukkan bahwa bukan shell yang melakukan ini, tetapi sistem di bawahnya. Bagaimana "Kesalahan segmentasi" dicetak? "Siapa" yang melakukannya? Kernel? Sesuatu yang lain Bagaimana sinyal dan semua efek sampingnya menyebar dari perangkat keras ke penghentian program pada akhirnya?


43
crshadalah ide bagus untuk eksperimen semacam ini. Terima kasih telah memberi tahu kami tentang hal itu dan gagasan di baliknya.
Bruce Ediger

30
Ketika saya pertama kali melihat crsh, saya pikir itu akan diucapkan "crash." Saya tidak yakin apakah itu nama yang pas.
jpmc26

56
Ini adalah eksperimen yang bagus ... tetapi Anda harus tahu apa system()fungsinya di bawah tenda. Ternyata itu system()akan menelurkan proses shell! Jadi proses shell Anda memunculkan proses shell lain dan bahwa proses shell (mungkin /bin/shatau sesuatu seperti itu) adalah salah satu yang menjalankan program. Cara /bin/shatau bashkerjanya adalah dengan menggunakan fork()dan exec()(atau fungsi lain dalam execve()keluarga).
Dietrich Epp

4
@BradenBest: Tepat. Baca halaman manual man 2 wait, itu akan termasuk makro WIFSIGNALED()dan WTERMSIG().
Dietrich Epp

4
@DietrichEpp Seperti yang Anda katakan! Saya mencoba menambahkan tanda centang agar (WIFSIGNALED(status) && WTERMSIG(status) == 11)mencetak sesuatu yang konyol ( "YOU DUN GOOFED AND TRIGGERED A SEGFAULT"). Ketika saya menjalankan segfaultprogram dari dalam crsh, itu dicetak persis seperti itu. Sementara itu, perintah yang keluar biasanya tidak menghasilkan pesan kesalahan.
Braden Best

Jawaban:


248

Semua CPU modern memiliki kapasitas untuk menginterupsi instruksi mesin yang sedang dijalankan. Mereka menyimpan cukup keadaan (biasanya, tetapi tidak selalu, di tumpukan) untuk memungkinkan untuk melanjutkan eksekusi nanti, seolah-olah tidak ada yang terjadi (biasanya instruksi yang terputus akan dimulai dari awal). Kemudian mereka mulai mengeksekusi pengendali interupsi , yang hanya kode mesin lebih banyak, tetapi ditempatkan di lokasi khusus sehingga CPU tahu di mana itu di muka. Interrupt handler selalu menjadi bagian dari kernel sistem operasi: komponen yang berjalan dengan hak istimewa terbesar dan bertanggung jawab untuk mengawasi pelaksanaan semua komponen lainnya. 1,2

Interupsi dapat bersifat sinkron , artinya dipicu oleh CPU itu sendiri sebagai respons langsung terhadap sesuatu yang dilakukan oleh instruksi yang saat ini dijalankan, atau asinkron , yang berarti bahwa itu terjadi pada waktu yang tidak dapat diprediksi karena peristiwa eksternal, seperti data yang tiba di jaringan Pelabuhan. Beberapa orang mencadangkan istilah "interupsi" untuk interupsi asinkron, dan memanggil interupsi sinkron "traps", "fault", atau "exception" sebagai gantinya, tetapi kata-kata itu semuanya memiliki arti lain sehingga saya akan tetap menggunakan "interrupt sinkron".

Sekarang, sebagian besar sistem operasi modern memiliki gagasan tentang proses . Pada dasarnya, ini adalah mekanisme di mana komputer dapat menjalankan lebih dari satu program pada saat yang sama, tetapi juga merupakan aspek kunci tentang bagaimana sistem operasi mengkonfigurasi perlindungan memori , yang merupakan fitur dari sebagian besar (tetapi, sayangnya, masih belum semua ) CPU modern. Ini berjalan bersama dengan memori virtual, yang merupakan kemampuan untuk mengubah pemetaan antara alamat memori dan lokasi aktual dalam RAM. Perlindungan memori memungkinkan sistem operasi untuk memberikan masing-masing proses potongan RAM sendiri, yang hanya dapat diakses olehnya. Hal ini juga memungkinkan sistem operasi (bertindak atas nama beberapa proses) untuk menetapkan wilayah RAM sebagai read-only, executable, dibagi di antara sekelompok proses yang bekerja sama, dll. Juga akan ada sejumlah memori yang hanya dapat diakses oleh inti. 3

Selama setiap proses mengakses memori hanya dengan cara yang dikonfigurasi CPU untuk memungkinkan, perlindungan memori tidak terlihat. Ketika suatu proses melanggar aturan, CPU akan menghasilkan interupsi sinkron, meminta kernel untuk menyelesaikan masalah. Secara teratur terjadi bahwa proses tidak benar - benar melanggar aturan, hanya kernel yang perlu melakukan beberapa pekerjaan sebelum proses dapat diizinkan untuk melanjutkan. Sebagai contoh, jika halaman memori proses perlu "diusir" ke file swap untuk membebaskan ruang dalam RAM untuk sesuatu yang lain, kernel akan menandai halaman itu tidak dapat diakses. Saat berikutnya proses mencoba menggunakannya, CPU akan menghasilkan interupsi perlindungan memori; kernel akan mengambil halaman dari swap, meletakkannya kembali di tempatnya, tandai itu dapat diakses kembali, dan melanjutkan eksekusi.

Tapi anggaplah proses itu benar-benar melanggar aturan. Itu mencoba mengakses halaman yang tidak pernah memiliki RAM yang dipetakan ke sana, atau mencoba untuk mengeksekusi halaman yang ditandai sebagai tidak mengandung kode mesin, atau apa pun. Keluarga sistem operasi umumnya dikenal sebagai "Unix" semua menggunakan sinyal untuk menghadapi situasi ini. 4 Sinyal mirip dengan interupsi, tetapi dihasilkan oleh kernel dan diteruskan oleh proses, bukannya dihasilkan oleh perangkat keras dan diteruskan oleh kernel. Proses dapat menentukan penangan sinyaldi kode mereka sendiri, dan beri tahu kernel di mana mereka berada. Penangan sinyal tersebut kemudian akan mengeksekusi, mengganggu aliran kontrol normal, bila perlu. Semua sinyal memiliki nomor dan dua nama, satu di antaranya adalah akronim samar dan yang lain frase sedikit lebih samar. Sinyal yang dihasilkan ketika proses melanggar aturan perlindungan memori adalah (dengan konvensi) nomor 11, dan namanya adalah SIGSEGV"Segmentasi kesalahan". 5,6

Perbedaan penting antara sinyal dan interupsi adalah bahwa ada perilaku default untuk setiap sinyal. Jika sistem operasi gagal menentukan handler untuk semua interupsi, itu adalah bug di OS, dan seluruh komputer akan macet ketika CPU mencoba memanggil handler yang hilang. Tetapi proses tidak berkewajiban untuk mendefinisikan penangan sinyal untuk semua sinyal. Jika kernel menghasilkan sinyal untuk suatu proses, dan sinyal itu telah dibiarkan pada perilaku standarnya, kernel hanya akan melanjutkan dan melakukan apa pun defaultnya dan tidak mengganggu proses. Sebagian besar perilaku default sinyal adalah "tidak melakukan apa-apa" atau "menghentikan proses ini dan mungkin juga menghasilkan dump inti." SIGSEGVadalah salah satu yang terakhir.

Jadi, untuk rekap, kami memiliki proses yang melanggar aturan perlindungan memori. CPU menghentikan proses dan menghasilkan interupsi sinkron. Kernel menerjunkan yang mengganggu dan menghasilkan SIGSEGVsinyal untuk proses. Mari kita asumsikan prosesnya tidak mengatur penangan sinyal SIGSEGV, jadi kernel melakukan perilaku default, yaitu untuk menghentikan proses. Ini memiliki semua efek yang sama dengan _exitpanggilan sistem: file yang terbuka ditutup, memori tidak dapat dialokasikan, dll.

Sampai saat ini tidak ada yang mencetak pesan yang dapat dilihat manusia, dan shell (atau, lebih umum, proses induk dari proses yang baru saja dihentikan) belum terlibat sama sekali. SIGSEGVpergi ke proses yang melanggar aturan, bukan induknya. Namun, langkah selanjutnya dalam urutan ini adalah memberi tahu proses induk bahwa anaknya telah dihentikan. Hal ini dapat terjadi dalam beberapa cara yang berbeda, dari yang paling sederhana adalah ketika orang tua sudah menunggu pemberitahuan ini, menggunakan salah satu waitpanggilan sistem ( wait, waitpid, wait4, dll). Dalam hal ini, kernel hanya akan menyebabkan panggilan sistem kembali, dan menyediakan proses induk dengan nomor kode yang disebut status keluar. 7 Status keluar memberitahu orang tua mengapa proses anak dihentikan; dalam hal ini, ia akan belajar bahwa anak itu dihentikan karena perilaku default dari suatu SIGSEGVsinyal.

Proses induk kemudian dapat melaporkan acara tersebut ke manusia dengan mencetak pesan; program shell hampir selalu melakukan ini. Anda crshtidak menyertakan kode untuk melakukan itu, tetapi itu tetap terjadi, karena rutin pustaka C systemmenjalankan shell berfitur lengkap /bin/sh,, "di bawah tenda". crshadalah kakek - nenek dalam skenario ini; notifikasi proses induk dipotong oleh /bin/sh, yang mencetak pesannya yang biasa. Kemudian /bin/shitu sendiri keluar, karena itu tidak ada lagi yang harus dilakukan, dan implementasi C perpustakaan dari systemmenerima bahwa pemberitahuan keluar. Anda dapat melihat pemberitahuan keluar itu dalam kode Anda, dengan memeriksa nilai balik darisystem; tetapi itu tidak akan memberi tahu Anda bahwa proses cucu meninggal dengan segfault, karena itu dikonsumsi oleh proses cangkang perantara.


Catatan kaki

  1. Beberapa sistem operasi tidak mengimplementasikan driver perangkat sebagai bagian dari kernel; namun, semua penangan interupsi masih harus menjadi bagian dari kernel, dan begitu juga kode yang mengkonfigurasi perlindungan memori, karena perangkat keras tidak mengizinkan apa pun kecuali kernel untuk melakukan hal-hal ini.

  2. Mungkin ada program yang disebut "hypervisor" atau "manajer mesin virtual" yang bahkan lebih istimewa daripada kernel, tetapi untuk keperluan jawaban ini dapat dianggap sebagai bagian dari perangkat keras .

  3. Kernel adalah sebuah program , tetapi itu bukan proses; itu lebih seperti perpustakaan. Semua proses menjalankan bagian dari kode kernel, dari waktu ke waktu, selain kode mereka sendiri. Mungkin ada sejumlah "utas kernel" yang hanya mengeksekusi kode kernel, tetapi mereka tidak menjadi perhatian kami di sini.

  4. Satu-satunya OS yang mungkin harus Anda hadapi lagi yang tidak dapat dianggap sebagai implementasi Unix, tentu saja, Windows. Itu tidak menggunakan sinyal dalam situasi ini. (Memang, itu tidak memiliki sinyal; pada Windows <signal.h>antarmuka sepenuhnya dipalsukan oleh perpustakaan C.) Ia menggunakan sesuatu yang disebut " penanganan pengecualian terstruktur " sebagai gantinya.

  5. Beberapa pelanggaran perlindungan memori menghasilkan SIGBUS("Bus error") alih-alih SIGSEGV. Garis antara keduanya tidak ditentukan dan bervariasi dari satu sistem ke sistem lainnya. Jika Anda telah menulis sebuah program untuk mendefinisikan handler SIGSEGV, mungkin ide yang baik untuk mendefinisikan handler yang sama SIGBUS.

  6. "Segmentasi fault" adalah nama interupsi yang dihasilkan untuk pelanggaran perlindungan memori oleh salah satu komputer yang menjalankan Unix asli , mungkin PDP-11 . " Segmentasi " adalah jenis perlindungan memori, tetapi saat ini istilah " kesalahan segmentasi " mengacu secara umum pada segala jenis pelanggaran perlindungan memori.

  7. Semua cara lain proses orang tua mungkin diberitahu tentang anak yang telah diakhiri, berakhir dengan panggilan orang tua waitdan menerima status keluar. Hanya saja sesuatu terjadi lebih dulu.


@ zvol: iklan 2) Saya rasa tidak benar untuk mengatakan bahwa CPU mengetahui segala sesuatu tentang proses. Anda harus mengatakan bahwa itu memanggil pengendali interupsi, yang mentransfer kontrol.
user323094

9
@ user323094 CPU multicore modern benar-benar tahu sedikit tentang proses; cukup sehingga, dalam situasi ini, mereka hanya dapat menunda thread eksekusi yang memicu kesalahan perlindungan memori. Juga, saya berusaha untuk tidak masuk ke detail tingkat rendah. Dari perspektif pemakai-ruang pemrogram, hal yang paling penting untuk dipahami tentang langkah 2 adalah perangkat keras yang mendeteksi pelanggaran perlindungan memori; kurang tepatnya pembagian kerja antara perangkat keras, firmware, dan sistem operasi dalam hal mengidentifikasi "proses menyinggung".
zwol

Kehalusan lain yang mungkin membingungkan pembaca yang naif adalah "Kernel mengirimkan sinyal SIGSEGV yang menyinggung proses." yang menggunakan jargon biasa, tetapi sebenarnya berarti bahwa kernel memberitahu dirinya sendiri untuk berurusan dengan sinyal foo pada bilah proses (yaitu kode userland tidak terlibat kecuali ada penangan sinyal diinstal, pertanyaan yang diselesaikan oleh kernel). Saya kadang-kadang lebih suka "menaikkan sinyal SIGSEGV pada proses" karena alasan itu.
dmckee

2
Perbedaan signifikan antara SIGBUS (kesalahan bus) dan SIGSEGV (kesalahan segmentasi) adalah ini: SIGSEGV terjadi ketika CPU tahu Anda tidak boleh mengakses alamat (dan karena itu tidak membuat permintaan bus memori eksternal). SIGBUS terjadi ketika CPU hanya mengetahui tentang masalah pengalamatan setelah ia menempatkan permintaan Anda pada bus alamat eksternal. Misalnya, meminta alamat fisik yang tidak ditanggapi oleh apa pun di bus, atau meminta untuk membaca data pada batas yang tidak selaras (yang akan membutuhkan dua permintaan fisik untuk mendapatkan alih-alih satu)
Stuart Caie

2
@StuartCaie Anda menggambarkan perilaku interupsi ; memang, banyak CPU membuat perbedaan yang Anda garis besar (meskipun beberapa tidak, dan garis antara keduanya bervariasi). The sinyal SIGSEGV dan SIGBUS, bagaimanapun, tidak andal dipetakan ke dua kondisi CPU-tingkat. Satu-satunya kondisi di mana POSIX membutuhkan SIGBUS daripada SIGSEGV adalah ketika Anda mmapfile ke wilayah memori yang lebih besar dari file, dan kemudian mengakses "seluruh halaman" di luar akhir file. (POSIX dinyatakan tidak jelas tentang kapan SIGSEGV / SIGBUS / SIGILL / etc terjadi.)
zwol

42

Shell memang ada hubungannya dengan pesan itu, dan crshsecara tidak langsung memanggil shell, yang mungkin bash.

Saya menulis sebuah program C kecil yang selalu kesalahan:

#include <stdio.h>

int
main(int ac, char **av)
{
        int *i = NULL;

        *i = 12;

        return 0;
}

Ketika saya menjalankannya dari shell default saya zsh,, saya mendapatkan ini:

4 % ./segv
zsh: 13512 segmentation fault  ./segv

Saat saya menjalankannya bash, saya mendapatkan apa yang Anda catat dalam pertanyaan Anda:

bediger@flq123:csrc % ./segv
Segmentation fault

Saya akan menulis penangan sinyal dalam kode saya, kemudian saya menyadari bahwa system()panggilan perpustakaan yang digunakan oleh crshshell eksekutif, /bin/shmenurut man 3 system. Itu /bin/shhampir pasti mencetak "kesalahan Segmentasi", karena crshtentu saja tidak.

Jika Anda menulis ulang crshuntuk menggunakan execve()system call untuk menjalankan program, Anda tidak akan melihat string "Kesalahan segmentasi". Itu berasal dari shell yang dipanggil oleh system().


5
Saya baru saja mendiskusikan hal ini dengan Dietrich Epp. Saya meretas bersama versi crsh yang menggunakan execvpdan melakukan tes lagi untuk menemukan bahwa sementara shell masih tidak crash (artinya SIGSEGV tidak pernah dikirim ke shell), ia tidak mencetak "Segmentasi Fault". Tidak ada yang dicetak sama sekali. Ini tampaknya menunjukkan bahwa shell mendeteksi ketika proses anaknya terbunuh dan bertanggung jawab untuk mencetak "kesalahan segmentasi" (atau beberapa varian darinya).
Braden Best

2
@BradenBest - Saya melakukan hal yang sama, kode saya lebih curang daripada kode Anda. Saya tidak mendapat pesan sama sekali, dan cangkang saya yang bahkan lebih tebal tidak mencetak apa-apa. Saya menggunakan waitpid()setiap fork / exec, dan mengembalikan nilai yang berbeda untuk proses yang memiliki kesalahan segmentasi, daripada proses yang keluar dengan status 0.
Bruce Ediger

21

Sepertinya saya tidak dapat menemukan informasi mengenai hal ini selain dari "MMU CPU mengirimkan sinyal" dan "kernel mengarahkannya ke program yang menyinggung, menghentikannya".

Ini sedikit ringkasan yang kacau. Mekanisme sinyal Unix sepenuhnya berbeda dari peristiwa khusus CPU yang memulai proses.

Secara umum, ketika alamat yang buruk diakses (atau ditulis ke area baca-saja, upaya untuk mengeksekusi bagian yang tidak dapat dieksekusi, dll.), CPU akan menghasilkan beberapa peristiwa khusus-CPU (pada arsitektur non-VM tradisional ini adalah disebut pelanggaran segmentasi, karena setiap "segmen" (secara tradisional, "teks" yang dapat dieksekusi hanya baca, "data" yang dapat ditulis dan panjang variabel, dan tumpukan yang secara tradisional berada di ujung memori) memiliki rentang alamat yang tetap - pada arsitektur modern, itu lebih cenderung menjadi kesalahan halaman [untuk memori yang belum dipetakan] atau pelanggaran akses [untuk membaca, menulis, dan mengeksekusi masalah izin], dan saya akan fokus pada hal ini untuk sisa jawabannya).

Sekarang, pada titik ini, kernel dapat melakukan beberapa hal. Kesalahan halaman juga dihasilkan untuk memori yang valid tetapi tidak dimuat (mis. Swap, atau dalam file yang di-mmaps, dll.), Dan dalam hal ini kernel akan memetakan memori dan kemudian memulai kembali program pengguna dari instruksi yang menyebabkan kesalahan. Kalau tidak, ia mengirim sinyal. Ini tidak persis "mengarahkan [acara asli] ke program yang menyinggung", karena proses untuk memasang penangan sinyal berbeda dan sebagian besar tidak bergantung pada arsitektur, vs. jika program tersebut diharapkan untuk mensimulasikan pemasangan penangan interrupt.

Jika program pengguna telah memasang penangan sinyal, ini berarti membuat bingkai tumpukan dan mengatur posisi eksekusi program pengguna ke penangan sinyal. Hal yang sama dilakukan untuk semua sinyal, tetapi dalam kasus pelanggaran segmentasi hal-hal umumnya diatur sehingga jika penangan sinyal kembali itu akan memulai kembali instruksi yang menyebabkan kesalahan. Program pengguna mungkin telah memperbaiki kesalahan, misalnya dengan memetakan memori ke alamat yang menyinggung - tergantung arsitektur apakah ini mungkin). Penangan sinyal juga dapat melompat ke lokasi yang berbeda dalam program (biasanya melalui longjmp atau dengan melemparkan pengecualian), untuk membatalkan operasi apa pun yang menyebabkan akses memori buruk.

Jika program pengguna tidak memiliki penangan sinyal yang diinstal, itu hanya dihentikan. Pada beberapa arsitektur, jika sinyal diabaikan itu dapat memulai kembali instruksi berulang-ulang, menyebabkan loop tak terbatas.


+1, hanya jawaban yang menambahkan apa pun ke yang diterima. Deskripsi yang bagus tentang sejarah "segmentasi". Fakta menyenangkan: x86 sebenarnya masih memiliki batasan segmen dalam mode yang dilindungi 32bit (dengan atau tanpa paging (memori virtual) diaktifkan), sehingga instruksi yang mengakses memori dapat menghasilkan #PF(fault-code)(kesalahan halaman) atau #GP(0)("Jika alamat efektif operan memori berada di luar CS, Batas segmen DS, ES, FS, atau GS. "). Mode 64bit menjatuhkan pemeriksaan batas segmen, karena OS hanya menggunakan paging saja, dan model memori datar untuk ruang pengguna.
Peter Cordes

Sebenarnya, saya percaya sebagian besar OS pada x86 menggunakan pagination tersegmentasi: sekelompok segmen besar di dalam ruang alamat paged yang rata. Inilah cara Anda melindungi dan memetakan memori kernel ke setiap ruang alamat: dering (tingkat perlindungan) ditautkan ke segmen, bukan halaman
Lorenzo Dematté

Juga, pada NT (tapi saya ingin tahu jika pada sebagian besar Unix adalah sama!) "Kesalahan segmentasi" bisa terjadi cukup sering: ada segmen 64k yang dilindungi di awal ruang pengguna, jadi dereferencing sebuah NULL pointer meningkatkan (tepat?) kesalahan segmentasi
Lorenzo Dematté

1
@ LorenzoDematté Ya, Unix modern yang seluruhnya atau hampir semuanya akan meninggalkan sebagian alamat yang tidak dipetakan secara permanen di awal ruang alamat untuk mendapatkan referensi NULL. Ini bisa sangat besar - pada sistem 64-bit, pada kenyataannya, itu mungkin empat gigabytes , sehingga pemotongan pointer ke 32 bit yang tidak disengaja akan segera ditangkap. Namun, segmentasi dalam arti x86 yang ketat hampir tidak digunakan sama sekali; ada satu segmen datar untuk ruang pengguna dan satu untuk kernel, dan mungkin beberapa untuk trik khusus seperti menggunakan FS dan GS.
zwol

1
@ LorenzoDematté NT menggunakan pengecualian daripada sinyal; dalam hal ini STATUS_ACCESS_VIOLATION.
Acak832

18

Kesalahan segmentasi adalah akses ke alamat memori yang tidak diizinkan (bukan bagian dari proses, atau mencoba untuk menulis data hanya baca, atau mengeksekusi data yang tidak dapat dieksekusi, ...). Ini ditangkap oleh MMU (Memory Management Unit, sekarang bagian dari CPU), menyebabkan gangguan. Interupsi ditangani oleh kernel, yang mengirimkan SIGSEGFAULTsinyal (lihat signal(2)misalnya) ke proses yang menyinggung. Penangan default untuk sinyal ini membuang inti (lihat core(5)) dan mengakhiri proses.

Shell sama sekali tidak memiliki tangan dalam hal ini.


3
Jadi pustaka C Anda, seperti glibc di Desktop, mendefinisikan string?
drewbenn

7
Perlu dicatat bahwa SIGSEGV dapat ditangani / diabaikan. Jadi mungkin untuk menulis sebuah program yang tidak dihentikan olehnya. Java Virtual Machine adalah salah satu contoh penting yang menggunakan SIGSEGV secara internal untuk tujuan yang berbeda, seperti yang disebutkan di sini: stackoverflow.com/questions/3731784/…
Karol Nowak

2
Demikian juga, pada Windows, .NET tidak repot-repot menambahkan pemeriksaan null pointer dalam banyak kasus - hanya menangkap pelanggaran akses (setara dengan segfaults).
immibis
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.