
Singkatnya: karena kami berkata begitu.
:)
Oke, penjelasan ini terlalu singkat untuk sebuah artikel, pembaca yang budiman, dan kata-kata provokatif saya membutuhkan penjelasan.
Pertemuan komite bahasa C - yang semula rencananya akan diadakan di Freiburg, Jerman, namun tidak berkembang bersama karena alasan yang jelas - berakhir pada 7 Agustus. Itu berjalan dengan baik, kami membuat kemajuan di semua lini. Ya, kami memang membuat kemajuan, saya jamin, dan C tidak mati.
Saya juga akan menyebutkan bahwa saya menjadi Editor proyek C, jadi sebelum mengambil judul sebagai pernyataan bodoh dari seseorang yang terlalu malas untuk "mencoba meningkatkan", saya ingin meyakinkan Anda bahwa saya sebenarnya bekerja sangat keras untuk memastikan bahwa C dapat untuk memenuhi kebutuhan pengembang tanpa harus mengacaukan 50 ekstensi khusus demi membangun perpustakaan dan aplikasi yang lebih atau kurang indah dan berguna.
Namun saya mengatakannya (bahwa bahasa C tidak akan pernah menghentikan Anda dari membuat kesalahan), yang berarti saya harus membenarkan. Kami dapat melihat ribuan CVE dan tiket terkait dengan sekumpulan kode C, atau kami dapat meminta MISRA untuk memeriksa dengan cermat setiap fitur C untuk kemungkinan penyalahgunaan ( halo, deklarasi prototipe K&R...) atau memiliki bug yang lebih kompleks dan lucu terkait dengan portabilitas dan perilaku yang tidak ditentukan. Tetapi sebaliknya kami membaca sumber aslinya - apa yang dikatakan Komite itu sendiri.
Oh, saatnya membeli popcorn ?!
Tidak ada pembaca yang budiman, kesampingkan popcorn. Seperti semua prosedur ISO, saya tidak bisa mengutip kata-kata orang lain, dan artikel ini tidak dimaksudkan untuk mempermalukan siapa pun. Tetapi saya akan menjelaskan mengapa sesuatu yang dengan mudah kita anggap sebagai perilaku buruk dalam dokumen ISO C yang memenuhi standar tidak akan pernah dikesampingkan. Dan mari kita mulai dengan dokumen oleh Dr. Philipp Klaus Krause:
N2526, gunakan const untuk data perpustakaan yang tidak akan dimodifikasi .
N2526 adalah dokumen yang sangat sederhana.
, , , . — , ! …
Saya setuju, ini tidak persis sama, tetapi saya yakin gagasan itu akan tampak masuk akal bagi Anda, pembaca yang budiman. Ketika dokumen ini dilakukan pemungutan suara, hampir tidak ada suara yang menentangnya. Belakangan, beberapa orang sangat keberatan karena proposal ini melanggar kode lama. Tentu saja, ini buruk: bahkan saya mengatur napas ketika berpikir untuk menambahkan
const? Tidak ada ABI dalam bahasa C yang dapat dipengaruhi oleh inovasi. C (implementasinya) bahkan tidak memperhatikan kualifikasi, bagaimana kita bisa merusak sesuatu ?! Mari kita lihat mengapa beberapa orang berpikir ini akan menjadi perubahan besar.
Bahasa C
Atau, seperti yang saya suka menyebutnya, "Keamanan jenis adalah untuk bahasa yang gagal." Ya, terlalu bertele-tele, jadi mari kita berhenti di "C". Anda mungkin bertanya-tanya mengapa saya mengatakan bahwa bahasa seperti C tidak aman untuk tipe. Bagaimanapun, inilah:
struct Meow {
int a;
};
struct Bark {
double b;
void* c;
};
int main (int argc, char* argv[]) {
(void)argc;
(void)argv;
struct Meow cat;
struct Bark dog = cat;
// error: initializing 'struct Bark' with an expression of incompatible type 'struct Meow'
return 0;
}
Sejujurnya, ini tampak seperti tipe pengaman yang kuat bagi saya, Jim! Dan semuanya menjadi lebih mengasyikkan:
#include <stdlib.h>
struct Meow {
int a;
};
struct Bark {
double b;
void* c;
};
int main (int argc, char* argv[]) {
(void)argc;
(void)argv;
struct Meow* p_cat = (struct Meow*)malloc(sizeof(struct Meow));
struct Bark* p_dog = p_cat;
// :3
return 0;
}
Ya, standar C memungkinkan dua tipe penunjuk yang sepenuhnya independen untuk merujuk satu sama lain. Kebanyakan kompiler akan memperingatkan Anda tentang ini, tetapi standar mengharuskan Anda untuk menerima kode ini kecuali Anda melepasnya
-Werror -Wall -Wpedantic, dll., Dll., Dll.
Nyatanya, kompilator dapat menerima ini tanpa transmisi eksplisit:
volatile(siapa yang membutuhkan semantik ini?!)const(tulis data hanya baca di sini!)_Atomic(keamanan benang!)
Saya tidak mengatakan bahwa Anda tidak boleh melakukan semua ini. Tetapi ketika Anda menulis dalam C - di mana sangat mudah untuk membuat fungsi dari 500-1000 baris dengan nama variabel yang benar-benar tidak dapat dipahami - Infa Sotka, bahwa Anda bekerja terutama dengan pointer, dan Anda biasanya kekurangan keamanan dalam hal bahasa dasar. Catatan: ini melanggar batasan, tetapi begitu banyak kode lama yang telah ditulis sehingga setiap implementasi mengabaikan kualifikasi, dan karena itu, kode Anda tidak akan dicegah untuk dikompilasi ( terima kasih @fanf!)! Dalam situasi ini, Anda dapat dengan mudah mengidentifikasi setiap potensi kegagalan dengan bantuan kompilator, dan Anda akan menerima peringatan, tetapi Anda tidak akan diminta untuk mengetik untuk memberi tahu kompilator apa yang sebenarnya ingin Anda lakukan. Lebih penting lagi, bagaimanapun, manusia yang datang setelah Anda juga tidak akan mengerti apa yang ingin Anda lakukan.
Yang perlu Anda lakukan hanyalah menghapus fitur tersebut
-Werror -Wall -Wpedantic, dan Anda akan siap melakukan kejahatan multithreading, mode hanya baca, dan register perangkat keras.
Semuanya adil sekarang, bukan? Jika seseorang menghapus semua peringatan dan tanda kesalahan itu, mereka tidak akan peduli kesalahan langkah atau hal bodoh apa yang Anda lakukan. Ini berarti bahwa pada akhirnya, peringatan ini sama sekali tidak relevan dan tidak berbahaya sejauh menyangkut kepatuhan ISO C. Namun ...
Kami sedang mempertimbangkan untuk melanggar peringatan
Iya.
Ini adalah neraka khusus yang digunakan oleh pengembang C dan pengembang C ++ pada tingkat yang lebih rendah. Peringatan itu mengganggu, dan, seperti yang diperlihatkan oleh latihan, termasuk
-Weverythingatau /W4, sangat mengganggu. Menyembunyikan peringatan variabel di namespace global (terima kasih, sekarang semua header dan library C menjadi masalah), menggunakan nama yang "dicadangkan" (seperti yang dikatakan anak-anak, " lol nice one xd !! "), dan "struktur ini memiliki padding karena Anda menggunakan alignof"(... ya, ya, saya tahu dia memiliki padding, saya secara eksplisit meminta lebih banyak padding, KARENA SAYA DIGUNAKAN alignof, MR. KOMPILATOR) - semua ini membutuhkan banyak waktu.
Tapi ini peringatan.
Meskipun menjengkelkan, mereka membantu Anda menghindari masalah. Fakta bahwa saya tanpa malu-malu dapat mengabaikan semua kualifikasi dan mengabaikan semua jenis keamanan baca, tulis, streaming, dan hanya-baca adalah perhatian utama dalam mengomunikasikan niat saya dan menghindari bug. Bahkan sintaks K&R yang lama menyebabkan bug dalam basis kode industri dan pemerintah karena pengguna melakukan sesuatu yang salah. Dan mereka melakukan ini bukan karena mereka programmer yang buruk, tetapi karena mereka bekerja dengan basis kode yang seringkali lebih tua dari mereka, dan bersiap untuk bertarung dengan itu. jutaan garis panjang. Tidak mungkin untuk menyimpan seluruh basis kode di kepala Anda: konvensi, analisis statis, peringatan tingkat tinggi, dan alat lain untuk ini. Sayangnya,
setiap orang ingin memiliki kode tanpa peringatan.
Artinya, saat developer GCC membuat peringatan menjadi lebih sensitif terhadap situasi yang berpotensi menimbulkan masalah, pengelola (bukan developer asli) secara tidak terduga menerima log tebal beberapa gigabyte dari kode lama, yang berisi banyak peringatan baru dan segala macam hal yang berbeda. "Ini kebodohan," kata mereka, "kode bekerja selama YEARS jadi mengapa GCC mengeluh sekarang?" Artinya, meskipun Anda menambahkan
constfungsi pada tanda tangan, meskipun secara moral, spiritual, dan sebenarnya benar, hal itu akan dihindari. "Melanggar" orang berarti "sekarang mereka harus mencari kode yang niatnya meragukan." Ini adalah kode yang dapat - karena menyebabkan Perilaku Tidak Terdefinisi - menghancurkan chip Anda atau merusak memori Anda.... Tapi ini adalah masalah lain yang menyertai profesi C-developer saat ini.
Umur sebagai ukuran kualitas
Berapa banyak orang yang bahkan berasumsi bahwa mereka
sudomemiliki kerentanan primitif seperti "-1 atau integer overflow memberikan akses ke semuanya"? Berapa banyak orang yang mengira Heartbleed bisa menjadi masalah nyata? Berapa banyak pengembang game yang mengirimkan pustaka stb “kecil” bahkan tanpa menggunakan phaser dan tidak menyadari bahwa pustaka ini berisi kerentanan input yang lebih penting daripada yang Anda bayangkan? Saya tidak mengkritik semua perkembangan ini atau penulisnya: mereka memberi kami bantuan penting, yang menjadi sandaran dunia selama beberapa dekade, seringkali dengan sedikit atau tanpa dukungan sampai beberapa masalah besar muncul. Tetapi orang-orang yang mengidolakan perkembangan ini dan membuatnya sendiri, kemudian mengeluarkan pepatah beracun dari diri mereka sendiri, menggambarkan kesalahan orang yang selamat:
, ?
Menjaga prinsip kompatibilitas ke belakang dan "santai" sebagai cita-cita tertinggi C, orang-orang yang bertahan cukup lama dalam industri ini mulai menyamakan usia dengan kualitas, seperti basis kode adalah tong anggur. Semakin tua dan lama kode yang digunakan, semakin halus dan halus anggurnya.
Sayangnya, semuanya tidak begitu romantis dan imut: penuh dengan bug, dengan banyaknya lubang keamanan, semua hutang teknis ini semakin berbahaya setiap hari. Seiring waktu, semua sistem berubah menjadi tumpukan busuk yang berumur paruh, tidak terawat dan sebagian tidak didukung. Mereka dibumbui dan diberi semangat kebangsawanan, tetapi pada kenyataannya mereka adalah mumi yang hanya menunggu untuk disodok dengan canggung, dan kemudian bisul kuno mereka yang bernanah akan meledak dan membanjiri aplikasi Anda dengan botulisme berpengalaman yang indah.
Hmm ... menjijikkan. Tapi bagaimana dengan Standar C?
Masalah yang saya perhatikan selama masa jabatan saya (yang sangat singkat) sebagai peserta rapat adalah bahwa kami mengutamakan kompatibilitas ke belakang. Bagi mereka yang bahkan bermigrasi ke C hari ini, kami berpegang pada aplikasi lama dan kasus penggunaannya dan menghilangkan kesempatan untuk meningkatkan keselamatan, keamanan, atau kesenian kode C. Proposal Dr. Krause sangat ringkas sehingga hampir tidak dapat disangkal: jika seseorang tidak menyukai peringatan , dia bisa mematikannya. Peringatan ini, bukan kesalahan, bukan untuk apa-apa: mesin C abstrak tidak memerlukanuntuk melakukan diagnostik, ISO C memungkinkan kode tersebut diterima dalam mode perakitan yang ketat. Dan itu akan membantu seluruh dunia untuk melepaskan diri dari API yang secara terbuka menyatakan, "mengubah konten yang kami sediakan untuk Anda adalah perilaku yang tidak ditentukan."
Namun, kami berubah pikiran tentang dokumen ini setelah diberikan sebagai alasan "kami tidak dapat memperkenalkan peringatan baru".
Argumen yang menentang proposal tersebut adalah: "Ada begitu banyak kode tertulis yang akan rusak jika kita mengubah tanda tangan ini." Ini, sekali lagi, membatasi perubahan pada peringatan dalam hal perilaku melanggar (ingat, konversi implisit yang menghapus kualifikasi - genap
_Atomic- sepenuhnya valid sesuai dengan ISO C, meskipun melanggar batasan). Jika itu masalahnya, setiap pembuat kompilator akan memperkenalkan sesuatu seperti Ages in Rust, For Warnings Only, untuk memberi orang patokan "stabil" untuk pengujian. Proposal ini bukanlah hal baru: Saya telah membaca dokumen serupa dari insinyur Coverity tentang membuat peringatan baru dan bagaimana pengguna bereaksi terhadapnya. Sulit untuk mengelola "kepercayaan" pengembang tentang peringatan baru dan hal lain. Butuh waktu lama untuk meyakinkan orang tentang kegunaannya. Bahkan John Carmack harus bekerja keras untuk mendapatkan peringatan dan kesalahan yang tepat dari alat analisis statisnya agar sesuai dengan perkembangannya, sebelum dia menyimpulkan bahwa "tidak bertanggung jawab untuk tidak menggunakan ini" .
Namun kami, Komite, tidak setuju untuk menambahkan
constfungsi penghasil nilai ke empat fungsi karena hal itu akan menambahkan peringatan ke kode yang berpotensi berbahaya. Kami keberatan dengan sintaks K&R lama yang tidak digunakan lagi, meskipun ada bukti kuat tentang pengawasan tidak bersalah dan kerentanan serius dalam menyampaikan jenis yang salah. Kami hampir menambahkan perilaku tidak terdefinisi ke preprocessor, hanya untuk menurunkannya, tetapi untuk membuat implementasi C "berperilaku sebagaimana mestinya". Karena kompatibilitas ke belakang, kami selalu berjalan di tepi untuk menghindari membuat kesalahan yang jelas. Dan ini, pembaca yang budiman, paling membuatku takut tentang masa depan S.
Standar C tidak melindungi Anda
Jangan salah: tidak peduli apa yang dikatakan programmer atau apa yang mereka bisikkan kepada Anda. Komite pengarah bahasa C sangat jelas. Kami tidak akan menambahkan peringatan baru ke kode lama Anda, meskipun kode ini bisa berbahaya. Kami tidak akan menahan Anda dari membuat kesalahan, karena itu dapat merusak gagasan tentang cara kerja kode lama Anda, yang mana itu salah. Kami tidak akan membantu pemula menulis kode C. Kami tidak akan meminta kode lama Anda untuk memenuhi Standar apapun. Setiap fitur baru akan menjadi opsional karena kami tidak dapat membayangkan memaksa penulis kompilator untuk tetap berpegang pada standar yang lebih tinggi atau mengharapkan lebih dari pengembang perpustakaan standar kami.
Kami akan membiarkan kompiler berbohong kepada Anda. Kami akan berbohong pada kode Anda. Dan ketika semuanya berjalan salah - akan ada kesalahan, "Oh, terjadi semacam sampah", akan ada kebocoran data - kami akan menggelengkan kepala dengan sungguh-sungguh. Kami akan membagikan ide-ide kami dan berdoa untuk Anda dan berkata, "Sayang sekali." Sungguh sayang ...
Mungkin suatu saat nanti kita akan memperbaikinya, pembaca yang budiman.