Dalam kelas Pemrograman Sistem yang saya ambil semester sebelumnya ini, kami harus mengimplementasikan klien dasar / server di C. Ketika menginisialisasi struct, seperti sock_addr_in
, atau buffer char (yang kami gunakan untuk mengirim data bolak-balik antara klien dan server) profesor menginstruksikan kami untuk hanya menggunakan bzero
dan tidak memset
menginisialisasi mereka. Dia tidak pernah menjelaskan mengapa, dan saya ingin tahu apakah ada alasan yang sah untuk ini?
Saya melihat di sini: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown yang bzero
lebih efisien karena fakta bahwa hanya akan menjadi memori zeroing, jadi tidak harus melakukan pengecekan tambahan yang memset
mungkin dilakukan. Itu masih belum tentu tampak seperti alasan untuk sama sekali tidak menggunakan memset
untuk mem-zero-up memori.
bzero
dianggap usang, dan lebih jauh lagi bukan fungsi standar C. Menurut manual, memset
lebih disukai daripada bzero
karena alasan ini. Jadi, mengapa Anda ingin tetap menggunakan bzero
lebih memset
? Hanya untuk keuntungan efisiensi, atau itu sesuatu yang lebih? Demikian juga, apa manfaat dari memset
kelebihan bzero
yang menjadikannya pilihan yang dipilih secara de facto untuk program yang lebih baru?
sumber
memset
mungkin sedikit kurang efisien karena "sedikit lebih banyak pengecekan" jelas merupakan kasus optimasi prematur: apa pun keuntungan yang mungkin Anda lihat dari menghilangkan satu atau dua instruksi CPU tidak sepadan ketika Anda dapat membahayakan portabilitas Anda. kode.bzero
sudah usang, dan itu cukup alasan untuk tidak menggunakannya.Jawaban:
Saya tidak melihat alasan untuk lebih memilih
bzero
lebihmemset
.memset
adalah fungsi standar C sementarabzero
tidak pernah menjadi fungsi standar C. Alasannya mungkin karena Anda dapat mencapai fungsionalitas yang sama persis menggunakanmemset
fungsi.Sekarang mengenai efisiensi, kompiler seperti
gcc
menggunakan implementasi builtinmemset
yang beralih ke implementasi tertentu ketika konstanta0
terdeteksi. Sama untukglibc
saat bawaan dinonaktifkan.sumber
memset
harus selalu digunakan dalam kasus ini, tetapi bingung mengapa kami tidak menggunakannya. Terima kasih telah mengklarifikasi, dan menegaskan kembali pikiran saya.bzero
implementasi yang rusak . Pada array non-aligned, ini digunakan untuk melampaui panjang yang disediakan dan nol lebih banyak byte. Tidak pernah mengalami masalah seperti itu setelah beralih kememset
.memset_s
yang harus digunakan jika Anda ingin memastikan kompiler tidak diam-diam mengoptimalkan-jauh panggilan untuk "menggosok" memori untuk beberapa tujuan terkait keamanan (seperti mengosongkan wilayah memori yang berisi sensitif sepotong informasi seperti kata sandi teks-bersih).Saya kira Anda menggunakan (atau guru Anda dipengaruhi oleh) Pemrograman Jaringan UNIX oleh W. Richard Stevens. Ia
bzero
sering menggunakan alih-alihmemset
, bahkan dalam edisi paling baru. Buku ini sangat populer, saya pikir itu menjadi idiom dalam pemrograman jaringan yang mengapa Anda masih melihatnya digunakan.Saya akan tetap dengan
memset
hanya karenabzero
sudah usang dan mengurangi portabilitas. Saya ragu Anda akan melihat keuntungan nyata dari menggunakan satu di atas yang lain.sumber
Satu keuntungan yang saya pikir
bzero()
lebih darimemset()
menetapkan memori ke nol adalah bahwa ada kemungkinan berkurangnya kesalahan.Lebih dari sekali saya menemukan bug yang terlihat seperti:
Kompiler tidak akan mengeluh (walaupun mungkin menaikkan beberapa tingkat peringatan pada beberapa kompiler) dan efeknya adalah memori tidak dihapus. Karena ini tidak membuang objek - hanya membiarkannya saja - ada kemungkinan yang baik bahwa bug mungkin tidak terwujud menjadi sesuatu yang jelas.
Fakta yang
bzero()
tidak standar adalah iritasi kecil. (FWIW, saya tidak akan terkejut jika sebagian besar panggilan fungsi dalam program saya tidak standar; bahkan menulis fungsi semacam itu adalah jenis pekerjaan saya).Dalam komentar untuk jawaban lain di sini, Aaron Newton mengutip yang berikut dari Pemrograman Jaringan Unix, Volume 1, Edisi ke-3 oleh Stevens, et al., Bagian 1.2 (penekanan ditambahkan):
Saya juga percaya bahwa sebagian besar panggilan ke
memset()
nol memori, jadi mengapa tidak menggunakan API yang disesuaikan dengan use case itu?Kelemahan yang mungkin untuk
bzero()
adalah bahwa kompiler mungkin lebih cenderung untuk mengoptimalkanmemcpy()
karena standar dan sehingga mereka mungkin ditulis untuk mengenalinya. Namun, perlu diingat bahwa kode yang benar masih lebih baik daripada kode yang salah yang telah dioptimalkan. Dalam kebanyakan kasus, menggunakanbzero()
tidak akan menyebabkan dampak yang nyata pada kinerja program Anda, dan itubzero()
bisa menjadi fungsi makro atau inline yang diperluasmemcpy()
.sumber
memset()
panggilan hanya untuk nol blok memori, yang saya pikir adalah argumen lain untukbzero()
. Apa arti huruf 'b'bzero()
?memset
melanggar pemesanan parameter umum "buffer, buffer_size" membuatnya IMO rawan kesalahan.Ingin menyebutkan sesuatu tentang argumen bzero vs memset. Instal ltrace dan kemudian bandingkan apa yang dilakukannya di bawah tenda. Di Linux dengan libc6 (2.19-0ubuntu6.6), panggilan yang dibuat persis sama (via
ltrace ./test123
):Saya telah diberitahu bahwa kecuali saya bekerja di dalam libc yang dalam atau sejumlah antarmuka kernel / syscall, saya tidak perlu khawatir tentang mereka. Yang harus saya khawatirkan adalah bahwa panggilan memenuhi persyaratan zero'ing buffer. Yang lain telah menyebutkan tentang mana yang lebih disukai daripada yang lain jadi saya akan berhenti di sini.
sumber
memset(ptr, 0, n)
ketika mereka melihatbzero(ptr, n)
dan mereka tidak dapat mengubahnya menjadi kode inline.extern void bzero(void *, size_t); void clear(void *p, size_t n) { bzero(p, n); }
menghasilkan panggilan kememset
. (Sertakanstddef.h
untuksize_t
tanpa apa-apa lagi yang bisa mengganggu.)Anda mungkin tidak boleh menggunakan
bzero
, itu sebenarnya bukan standar C, itu adalah hal POSIX.Dan perhatikan bahwa kata "adalah" - kata itu sudah tidak digunakan lagi di POSIX.1-2001 dan dihapus di POSIX.1-2008 sebagai penghormatan untuk memset agar Anda lebih baik menggunakan fungsi standar C.
sumber
bzero
bukan bagian dari itu.Untuk fungsi memset, argumen kedua adalah
int
dan argumen ketiga adalahsize_t
,yang biasanya merupakan
unsigned int
, tetapi jika nilai-nilai seperti,0 and 16
untuk argumen kedua dan ketiga masing-masing dimasukkan dalam urutan yang salah seperti 16 dan 0 maka, panggilan untuk memset tersebut masih dapat berfungsi, tetapi tidak akan melakukan apa-apa. Karena jumlah byte yang diinisialisasi ditentukan sebagai0
.Kesalahan seperti itu dapat dihindari dengan menggunakan bzero, karena menukar dua argumen ke bzero akan selalu ditangkap oleh kompiler C jika fungsi prototipe digunakan.
sumber
Singkatnya:
memset
membutuhkan lebih banyak operasi perakitanbzero
.Ini adalah sumbernya: http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown
sumber
Silakan sesuka Anda. :-)
Perhatikan bahwa:
bzero
tidak mengembalikan apa-apa,memset
mengembalikan penunjuk kosong (d
). Ini dapat diperbaiki dengan menambahkan typecast untuk membatalkan dalam definisi.#ifndef bzero
tidak mencegah Anda menyembunyikan fungsi asli bahkan jika itu ada. Ini menguji keberadaan makro. Ini dapat menyebabkan banyak kebingungan.bzero
melalui pointer fungsi, ini tidak akan berfungsi.sumber
bzero
via pointer fungsi, ini tidak akan berfungsi.bzero
. Ini adalah kekejaman.memset mengambil 3 parameter, bzero mengambil 2 dalam memori dibatasi bahwa parameter tambahan akan mengambil 4 byte lebih dan sebagian besar waktu itu akan digunakan untuk mengatur semuanya menjadi 0
sumber