Pengaturcaraan C

malloc dalam bahasa c

malloc dalam bahasa c
Anda boleh datang ke sini kerana dua sebab: sama ada anda ingin memperuntukkan kandungan secara dinamik, atau anda ingin mengetahui lebih lanjut mengenai cara malloc berfungsi. Dalam kedua-dua keadaan, anda berada di tempat yang betul! Peruntukan dinamik adalah proses yang banyak berlaku tetapi secara amnya kita tidak menggunakannya sendiri: sebahagian besar bahasa pengaturcaraan menguruskan memori untuk anda kerana ia adalah kerja yang sukar dan jika anda gagal melakukannya dengan betul, ada implikasi keselamatan.

Walau bagaimanapun, jika anda melakukan C, C ++ atau kod pemasangan, atau jika anda melaksanakan modul luaran baru dalam bahasa pengaturcaraan kegemaran anda, anda perlu menguruskan peruntukan memori dinamik anda sendiri.

Apa itu peruntukan dinamik? Mengapa saya memerlukan malloc?

Baiklah, dalam semua aplikasi, apabila anda membuat pemboleh ubah baru - ia sering disebut menyatakan pemboleh ubah - anda memerlukan memori untuk menyimpannya. Oleh kerana komputer anda berada di zaman moden, komputer dapat menjalankan lebih dari satu aplikasi dalam satu masa dan setiap aplikasi harus memberitahu OS anda (di sini Linux) bahawa memerlukan sejumlah memori. Semasa anda menulis kod seperti ini:

#sertakan
#sertakan
#tentukan DISK_SPACE_ARRAY_LENGTH 7
batal getFreeDiskSpace (int statsList [], size_t listLength)
kembali;

int utama ()
/ * Mengandungi ruang cakera kosong selama 7 hari terakhir. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
pulangkan EXIT_SUCCESS;

Array freeDiskSpace memerlukan memori jadi anda perlu meminta persetujuan Linux untuk mendapatkan sedikit memori. Walau bagaimanapun, kerana jelas ketika membaca kod sumber bahawa anda memerlukan array 7 int, penyusun secara automatik meminta Linux untuknya, dan ia akan memperuntukkannya di timbunan. Ini pada dasarnya bermaksud bahawa penyimpanan ini akan musnah ketika anda mengembalikan fungsi di mana pemboleh ubah dinyatakan. Itulah sebabnya anda tidak boleh melakukannya:

#sertakan
#sertakan
#tentukan DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/ * KENAPA KITA MELAKUKANNYA?! statsList akan DITURUNKAN! * /
kembali statsList;

int utama ()
/ * Mengandungi ruang cakera kosong selama 7 hari terakhir. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
pulangkan EXIT_SUCCESS;

Anda melihat dengan lebih mudah masalahnya sekarang? Kemudian, anda mahu menggabungkan dua rentetan. Dalam Python dan JavaScript, anda akan melakukan:

newStr = str1 + str2

Tetapi seperti yang anda ketahui, di C ia tidak berfungsi seperti ini. Oleh itu, untuk membina URL misalnya, anda perlu menggabungkan dua rentetan, seperti jalur URL dan nama domain. Di C, kita ada strat, betul, tetapi hanya berfungsi jika anda mempunyai array dengan cukup ruang untuknya.

Anda akan tergoda untuk mengetahui panjang tali baru dengan menggunakan strlen, dan anda pasti betul. Tetapi kemudian, bagaimana anda meminta Linux untuk menyimpan jumlah memori yang tidak diketahui ini? Pengkompil tidak dapat menolong anda: ruang tepat yang ingin anda peruntukkan hanya diketahui pada waktu runtime. Di situlah anda memerlukan peruntukan dinamik, dan malloc.

Menulis fungsi C pertama saya menggunakan malloc

Sebelum menulis kod, sedikit penjelasan: malloc membolehkan anda memperuntukkan sebilangan bait tertentu untuk penggunaan aplikasi anda. Ia sangat mudah digunakan: anda memanggil malloc dengan bilangan bait yang anda perlukan, dan ia mengembalikan penunjuk ke kawasan baru anda yang disediakan oleh Linux untuk anda.

Anda hanya mempunyai 3 tanggungjawab:

  1. Periksa sama ada malloc mengembalikan NULL. Itu berlaku apabila Linux tidak mempunyai cukup memori untuk disediakan.
  2. Bebaskan pemboleh ubah anda setelah tidak digunakan. Jika tidak, anda akan membuang memori dan ini akan memperlahankan aplikasi anda.
  3. Jangan sekali-kali menggunakan zon memori setelah anda membebaskan pemboleh ubah.

Sekiranya anda mengikuti semua peraturan ini, semuanya akan berjalan lancar dan peruntukan dinamik akan menyelesaikan banyak masalah kepada anda. Kerana anda memilih bila anda membebaskan memori, anda juga dapat mengembalikan pemboleh ubah yang diperuntukkan dengan malloc. Cuma, jangan lupa untuk membebaskannya!

Sekiranya anda tertanya-tanya bagaimana membebaskan pemboleh ubah, itu dengan fungsi bebas. Panggil dengan penunjuk yang sama dengan malloc yang mengembalikan anda, dan memori dibebaskan.

Mari saya tunjukkan dengan contoh ringkas:

#sertakan
#sertakan
#sertakan
/ *
* Semasa memanggil fungsi ini, jangan lupa untuk memeriksa apakah nilai kembali adalah NULL
* Sekiranya tidak NULL, anda mesti memanggil percuma pada penunjuk yang dikembalikan setelah nilai
* tidak lagi digunakan.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/ * Pemeriksaan keselamatan. * /
jika (baseUrl == NULL || toolPath == NULL)
kembali NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * Jangan lupa '\ 0', maka +1. * /
finalUrl = malloc (sizeof (char) * (finalUrlLen + 1));
/ * Mengikuti peraturan malloc… * /
jika (finalUrl == NULL)
kembali NULL;

strcpy (finalUrl, baseUrl);
strcat (finalUrl, toolPath);
kembali finalUrl;

int utama ()
char * googleImages = NULL;
googleImages = getUrl ("https: // www.google.com "," / imghp ");
jika (googleImages == NULL)
pulangkan EXIT_FAILURE;

meletakkan ("URL Alat:");
meletakkan (googleImages);
/ * Tidak diperlukan lagi, bebaskan. * /
percuma (googleImages);
googleImages = NULL;
pulangkan EXIT_SUCCESS;

Oleh itu, anda melihat contoh praktikal untuk menggunakan peruntukan dinamik. Pertama, saya mengelakkan perangkap seperti memberi nilai pulangan getUrl terus ke fungsi meletakkan. Kemudian, saya juga meluangkan masa untuk memberi komen dan mendokumentasikan fakta bahawa nilai kembali harus dibebaskan dengan betul. Saya juga memeriksa nilai NULL di mana-mana supaya apa-apa yang tidak dijangka dapat ditangkap dengan selamat dan bukannya merosakkan aplikasi.

Akhirnya, saya dengan berhati-hati membebaskan pemboleh ubah dan kemudian menetapkan penunjuk ke NULL. Itu mengelakkan tergoda untuk menggunakan - walaupun secara tidak sengaja - zon memori yang kini dibebaskan. Tetapi seperti yang anda lihat, mudah untuk membebaskan pemboleh ubah.

Anda mungkin menyedari bahawa saya menggunakan sizeof di malloc. Ini memungkinkan untuk mengetahui berapa banyak byte yang digunakan char dan menjelaskan maksud dalam kod sehingga lebih mudah dibaca. Untuk char, sizeof (char) selalu sama dengan 1, tetapi jika anda menggunakan array int, ia berfungsi dengan cara yang sama. Sebagai contoh, jika anda perlu menempah 45 int, lakukan:

fileSizeList = malloc (sizeof (int) * 45);

Dengan cara ini, anda dapat dengan cepat melihat berapa banyak yang anda mahu peruntukkan, sebab itulah saya selalu mengesyorkan penggunaannya.

Bagaimana cara kerja malloc di bawah tudung?

malloc dan percuma, sebenarnya, adalah fungsi yang termasuk dalam semua program C yang akan bercakap dengan Linux bagi pihak anda. Ini juga akan menjadikan peruntukan dinamik lebih mudah kerana, pada mulanya, Linux tidak membenarkan anda memperuntukkan pemboleh ubah dari semua ukuran.

Linux menyediakan dua cara untuk mendapatkan lebih banyak memori sebenarnya: sbrk dan mmap. Kedua-duanya mempunyai batasan, dan salah satunya adalah: anda boleh memperuntukkan jumlah yang agak besar, seperti 4.096 bait atau 8.192 bait. Anda tidak boleh meminta 50 bait seperti yang saya contohkan, tetapi anda juga tidak boleh meminta 5,894 bait.

Ini mempunyai penjelasan: Linux perlu menyimpan jadual di mana ia memberitahu aplikasi mana yang telah memesan zon memori mana. Dan jadual ini menggunakan ruang juga, jadi jika setiap bait memerlukan baris baru dalam tabel ini, sebahagian besar memori akan diperlukan. Itulah sebabnya memori terpecah dalam blok besar, misalnya, 4,096 bait, dan seperti anda tidak dapat membeli 2 oren setengah dalam runcit, anda tidak boleh meminta setengah blok.

Jadi malloc akan mengambil blok besar ini dan memberi anda sedikit potongan blok memori ini setiap kali anda memanggilnya. Juga, jika anda membebaskan beberapa pemboleh ubah, tetapi tidak cukup untuk membenarkan membebaskan keseluruhan blok, sistem malloc dapat menyimpan blok dan mengitar semula zon memori ketika anda memanggil malloc lagi. Ini mempunyai manfaat untuk menjadikan malloc lebih cepat, namun memori yang disediakan oleh malloc tidak dapat digunakan dalam aplikasi lain, sementara program saat ini tidak menggunakannya.

Tetapi malloc pintar: jika anda memanggil malloc untuk memperuntukkan 16 MiB atau sejumlah besar, malloc mungkin akan meminta Linux untuk blok penuh yang dikhaskan hanya untuk pemboleh ubah besar ini dengan menggunakan mmap. Dengan cara ini, apabila anda menelefon percuma, kemungkinan besar akan mengelakkan pembaziran ruang. Jangan risau, malloc melakukan pekerjaan yang lebih baik semasa mengitar semula daripada yang dilakukan manusia dengan sampah kita!

Kesimpulannya

Saya rasa sekarang anda lebih memahami bagaimana semua itu berfungsi. Sudah tentu, peruntukan dinamik adalah topik besar dan saya rasa kita boleh menulis buku lengkap mengenai topik ini, tetapi artikel ini semestinya membuat anda selesa dengan konsepnya secara umum dan dengan nasihat pengaturcaraan praktikal.

Alat Berguna untuk Pemain Linux
Sekiranya anda suka bermain permainan di Linux, kemungkinan anda telah menggunakan aplikasi dan utiliti seperti Wine, Lutris dan OBS Studio untuk meni...
HD Remastered Games untuk Linux yang Tidak Pernah Melancarkan Linux Sebelumnya
Banyak pembangun dan penerbit permainan hadir dengan penghapus HD permainan lama untuk memperpanjang usia francais, harap peminat meminta keserasian d...
Cara Menggunakan AutoKey untuk Mengautomasikan Permainan Linux
AutoKey adalah utiliti automasi desktop untuk Linux dan X11, yang diprogramkan dalam Python 3, GTK dan Qt. Dengan menggunakan skrip dan fungsi MACRO, ...