Halo dan selamat datang. Sekarang kita memahami alokasi memori dinamis,
kita harus mengimplementasikannya, kita harus benar-benar tahu bagaimana melakukannya dalam kode c.
Jadi kita akan berbicara tentang tiga fungsi yang
sangat penting, malloc, calloc, realloc.
Anda melihat bahwa mereka memiliki nama di mana
alokasi memori calloc dan realokasi.
Cara paling sederhana dan paling umum untuk mengalokasikan memori
adalah melalui fungsi perpustakaan standar bernama malloc.
Ini mengalokasikan memori dinamis saat runtime.
Untuk memanggil fungsi ini, Anda harus menyertakan file header lib standar.
Anda menentukan jumlah byte memori yang ingin Anda alokasikan sebagai argumennya.
Apa yang dikembalikan dari fungsi ini adalah alamat byte pertama dari memori yang dialokasikan.
Karena Anda mendapatkan alamat yang dikembalikan, pointer adalah satu-satunya tempat untuk meletakkannya.
Jadi inilah mengapa alokasi memori dinamis hanya dimungkinkan melalui
konsep pointer ini karena ia mengembalikan alamat.
Anda hanya bisa meletakkan alamat di pointer, itulah yang disimpan oleh pointer, pointer menyimpan alamat.
Jadi, inilah cara Anda melakukannya dengan sintaks yang sangat sederhana.
Biasanya, saat membuat pointer, Anda tidak perlu melakukannya.
Anda bisa membuat pointer Anda dan mengaturnya ke nol.
Dan kemudian di baris berikutnya, Anda bisa malloc.
Tapi di sini adalah sintaks standar yang Anda buat pointer int Anda,
pointer ke tipe int.
Dan kemudian Anda akan melihat bahwa Anda memanggil malloc.
Dan di sini, kita katakan malloc, kita akan membuat 100 byte untuk
malloc dan kemudian kita akan melemparkannya ke pointer int.
Karena malloc hanya mengembalikan alamat, Anda harus mentransmisikannya
ke penunjuk akhir karena alamat itu
menyimpan penunjuk int.
Ini adalah cara standar untuk melakukannya.
Sekarang Anda meminta 100 byte memori
dan menetapkannya ke alamat blok memori ke nomor p.
pNumber akan menunjuk ke lokasi int pertama di awal 100 byte yang dialokasikan.
Jadi artinya ini karena bilangan bulat adalah 4 byte, ia dapat
menampung 25 nilai int.
Dan sekali lagi, ini dengan asumsi Anda memiliki 4 byte.
Sekarang tergantung pada sistem yang Anda jalankan, mereka mungkin lebih besar, mungkin lebih kecil.
Jadi Anda harus melihat masalah dengan ini. Kode ini tidak
akan bekerja pada sistem yang berbeda karena Anda mengalokasikan berdasarkan
asumsi, berdasarkan asumsi ukuran int.
Jadi tidak baik menggunakan malloc dengan
cara ini dengan angka konstan 100.
Yang ingin Anda lakukan adalah Anda ingin menggunakan operator sizeof.
Jadi akan lebih baik untuk menghilangkan asumsi bahwa int adalah 4 byte.
Sebaliknya jika Anda ingin mengalokasikan ruang untuk 25 bilangan bulat di dalam argumen
malloc, tentukan jumlah bilangan
bulat yang ingin Anda alokasikan dan kemudian kalikan dengan ukuran bilangan bulat.
Dan ini akan membuat kode lebih portabel.
Kode ini sekarang akan bekerja pada sistem yang berbeda, sistem operasi yang berbeda, arsitektur yang berbeda.
Anda masih memberikan nilai pengembalian alamat karena harus menunjuk ke tipe int,
jadi Anda mengatakan int bintang. Satu-satunya perbedaan di sini adalah Anda menggunakan operator sizeof.
Operator sizeof sangat penting ketika Anda mengalokasikan memori menggunakan malloc atau
menggunakan calloc atau realoc.
Anda selalu menggunakan dan ingin menggunakan operator sizeof
untuk jenis yang Anda alokasikan dan kemudian mengalikannya dengan berapa banyak
angka tertentu yang Anda inginkan, jadi jika Anda ingin
menyimpan 25 int, lakukan 25.
Jadi argumen malloc di atas dengan jelas menunjukkan bahwa byte yang cukup untuk
menampung 25 nilai tipe int harus tersedia.
Juga, seperti yang saya sebutkan, perhatikan para pemainnya. Ini mengubah alamat, yang
dikembalikan oleh fungsi ke penunjuk tipe menjadi int dan penunjuk int.
Malloc mengembalikan pointer bertipe void, itulah yang membuatnya sangat berguna.
Ini mengembalikan alamat itu tetapi itu adalah penunjuk kosong.
Ingat, kita berbicara tentang pointer kosong dan mengapa pointer kosong berguna
karena sekarang Anda dapat memiliki fungsi yang dapat mengambil parameter yang berbeda dan dapat
mengembalikan pointer kosong. Sekarang Anda melihat kekuatan
mengembalikan pointer kosong, sekali lagi, tetapi
untuk menggunakannya, ke d untuk benar-benar menetapkan data padanya, untuk menghilangkan referensi, Anda
harus membuangnya.
Jika kami tidak ingin membuang ini, kami dapat mengatakan nomor p bintang batal.
Kami tidak mentransmisikannya, tetapi pada akhirnya kami harus mentransmisikannya
begitu kami ingin menghapus referensinya.
Tapi itulah kenapa kita harus cast dari malloc. Itu mengembalikan alamat dan Anda ingin itu menunjuk
ke tipe int, dan itu mengembalikan tipe void.
Anda dapat meminta sejumlah byte.
Namun, itu tergantung pada sistem Anda dan berapa banyak memori yang Anda miliki di sistem Anda.
Jadi jika Anda mencoba membuat atau mencoba meminta satu ton byte atau
ada batasan tertentu, itu bisa gagal.
Dan ketika gagal, ia mengembalikan nilai nol, malloc akan mengembalikan nol.
Dan ini bagus karena pointer ketika pointer menunjuk nol, itu berarti mereka tidak menunjuk ke
memori apa pun, jadi Anda tidak
dapat merusak atau mengubah memori apa pun secara tidak sengaja.
Jadi, selalu merupakan ide yang baik setelah Anda
melakukan malloc untuk segera memeriksa null sebelum Anda
menggunakannya, sama seperti saat Anda
menetapkan data atau seperti saat Anda menghapus referensi sebuah pointer.
Anda ingin memastikan bahwa Anda benar-benar menunjuk ke sesuatu.
Jadi di sini, kami mengalokasikan beberapa memori untuk nomor p pointer kami dan
kemudian kami mengatakan jika bukan nomor p.
Ingat, nol adalah nol.
Jadi Anda bisa menggunakan not di atasnya. Anda tidak harus benar-benar membandingkannya dengan nol.
Anda bisa, Anda bisa membandingkannya dengan null itu membuatnya lebih mudah dibaca, mungkin membuatnya lebih eksplisit.
Tapi Anda bisa mengatakan bukan angka p, dan itu sebenarnya mengatakan bukan
satu, dan nol adalah nol. Jadi ini akan memeriksa nol.
Dan jika itu nol, itu pada dasarnya berarti
bahwa memori tidak dapat dialokasikan. Jika Anda tidak dapat mengalokasikan memori dalam program Anda, Anda berada dalam masalah.
Jadi apa yang biasanya Anda lakukan dalam kode ini untuk menangani kegagalan
alokasi memori adalah Anda harus membatalkan, Anda harus memanggil
exit, Anda harus keluar dari program Anda. Karena jika program Anda tidak dapat mengalokasikan memori, program Anda disemprot.
Jadi biasanya ini yang Anda sebut batalkan kecelakaan jika Anda tidak dapat mengalokasikan memori.
Setidaknya ketika Anda melakukan ini, Anda dapat menampilkan pesan
mengakhiri program. Ini jauh lebih
baik daripada membiarkan program untuk melanjutkan ketika Anda tidak kami tidak dapat mengalokasikan memori.
Karena kemudian Anda dapat melanjutkan, Anda dapat mencoba menggunakan memori
itu, itu akan menjadi nol, jadi program akan tetap macet tetapi
Anda belum tentu tahu mengapa.
Anda harus melihat tumpukan panggilan. Ini akan memakan waktu lebih lama untuk men-debug kesalahan itu.
Melepaskan memori. Sekarang saya menyebutkan bahwa
karena Anda adalah programmer yang bertanggung jawab untuk mengalokasikan memori, Anda
harus membuang memori ketika Anda tidak lagi menggunakan karena memori adalah sumber
daya penting, terutama pada sistem tertanam.
Anda tidak boleh menggunakan memori jika tidak membutuhkannya. Jadi Anda harus melepaskan memori.
Anda selalu ingin melepaskan memori saat tidak lagi diperlukan.
Memori yang Anda alokasikan di heap akan dilepaskan secara otomatis saat program Anda ada,
yang bagus karena melakukan pembersihan.
Tetapi jauh lebih baik untuk melepaskan memori secara eksplisit ketika Anda selesai dengannya
bahkan jika itu tepat sebelum Anda keluar.
Lebih bersih,
selalu lakukan gratis atau selalu lepaskan memori setelah Anda mengalokasikannya,
Anda ingin mengikuti aturan ini. Ini adalah aturan ketat yang ketat.
Selalu lepaskan memori jika Anda mengalokasikannya.
Kebocoran memori terjadi saat Anda mengalokasikan beberapa memori secara dinamis dan
Anda tidak menyimpan referensi sehingga Anda tidak dapat melepaskannya.
Mungkin Anda berada di luar cakupan untuk referensi yang tidak bisa Anda lakukan. Anda tidak melepaskannya.
Itu disebut kebocoran memori. Ada memori yang dialokasikan tetapi tidak lagi digunakan.
Ini sering terjadi saat Anda berada dalam satu lingkaran, dan Anda mengalokasikan memori dalam satu lingkaran.
Anda berada di lingkaran. Anda mengalokasikan memori ini. Anda menggunakannya di dalam loop,
dan kemudian Anda melompat keluar dari loop dan Anda tidak lagi melepaskannya.
Setiap iterasi loop mengalokasikannya.
Jadi untuk mengosongkan memori yang telah Anda alokasikan secara dinamis,
Anda harus tetap memiliki akses ke alamat tersebut.
Jadi biasanya Anda menginginkan memori bebas setelah selesai menggunakannya dan
biasanya dalam metode yang Anda alokasikan.
Namun, jika Anda meneruskan memori itu ke fungsi lain dan itu
adalah tanggung jawab fungsi itu, tetapi biasanya Anda ingin melepaskan memori dan
fungsi yang Anda alokasikan.
Untuk melepaskan memori untuk blok memori yang dialokasikan secara
dinamis yang alamatnya telah Anda simpan dalam sebuah pointer, yang harus Anda
lakukan hanyalah memanggil fungsi bebas.
Ini juga ada di lib standar. Anda cukup meneruskan pointer ke fungsi gratis.
Dan biasanya, setelah Anda meneruskan penunjuk itu, Anda ingin menyetelnya ke nol karena
itu artinya Anda tidak memiliki memori yang dialokasikan untuk itu.
Fungsi bebas memiliki parameter formal bertipe bintang batal, sehingga
Anda dapat meneruskan jenis penunjuk apa pun
dan itu akan berfungsi.
Anda tidak harus benar-benar melemparkannya atau semacamnya.
Selama nomor p berisi alamat yang dikembalikan ketika memori dialokasikan, seluruh blok memori
akan bebas untuk digunakan lebih lanjut. Program lain dapat menggunakan memori itu, program
Anda sekarang dapat menggunakan memori
itu, signifikan saat Anda menggunakan sistem tertanam.
Dan seperti yang saya sebutkan, Anda selalu ingin menyetel penunjuk
ke nol untuk menandakan bahwa penunjuk itu tidak lagi menunjuk ke apa pun.
Memori itu telah dibebaskan.
Ada fungsi bagus lain yang disebut calloc.
Ini memiliki beberapa keunggulan dibandingkan malloc. Ini sangat mirip dengan
malloc, tetapi apa yang dilakukannya adalah mengalokasikan memori sebagai sejumlah elemen dalam
ukuran tertentu dan juga menginisialisasi memori.
Itulah bedanya, inisialisasi. Saya berbicara tentang pentingnya inisialisasi.
Itulah mengapa
Anda selalu ingin menginisialisasi data sehingga Anda memahami bahwa ada data
di sana yang Anda harapkan.
Saat Anda tidak menginisialisasi data, mungkin ada data di sana yang tidak Anda ketahui.
Jadi selalu inisialisasi data Anda dengan sesuatu.
Dan calloc sedikit lebih baik karena melakukannya untuk Anda.
Dibutuhkan dua argumen, memiliki dua parameter.
Jumlah item data yang membutuhkan ruang, ukuran setiap item data.
Itu dideklarasikan di header lib standar.
Anda menyebutnya seperti Anda memanggil malloc. Terlihat hampir sama.
Dalam contoh ini, kami membuat
pointer integer, dan kami mengalokasikan 75 integer
sizeof int. Jadi dibutuhkan dua parameter.
Ini sedikit lebih bersih karena Anda tidak harus benar-benar melakukan perkalian.
Di malloc, Anda harus melakukan 75 kali acara.
Di sini Anda hanya mengatakan
75, Anda membuat 75 int dan ukuran untuk masing-masing adalah 4 byte
atau apa pun yang dikembalikan sistem dari ukuran operator.
Tetapi sekali lagi pentingnya ini adalah ini akan menginisialisasi semua data itu juga, nilai
pengembaliannya bisa nol jika tidak dapat mengalokasikan memori itu yang pada gilirannya tidak boleh Anda batalkan.
Tapi itu sangat mirip dengan menggunakan malloc kecuali plus besar adalah inisialisasi ini.
Semua int diinisialisasi ke nol, dan itu benar-benar masalah besar,
keuntungan besar.
Ini juga sedikit lebih mudah digunakan dengan dua parameter.
Mari kita bicara tentang fungsi lain yang disebut realloc.
Fungsi realloc memungkinkan Anda untuk menggunakan kembali atau memperluas memori yang sebelumnya
Anda alokasikan menggunakan malloc atau calloc.
Jadi ini adalah cara untuk secara dinamis mengubah berapa banyak memori yang
dialokasikan saat Anda menjalankan.
Jadi Anda awalnya bisa membuat begitu banyak memori dan kemudian Anda menyadari
bahwa, itu tidak cukup memori. Nah, yang dapat Anda lakukan di sana adalah Anda
bisa memanggil realoc, dan ini akan mengalokasikan memori.
Ini mengharapkan dua nilai argumen, sebuah pointer yang berisi alamat
yang sebelumnya diubah oleh panggilan ke malloc.
Jadi Anda memiliki pointer yang memiliki beberapa memori yang dialokasikan atau calloc dan kemudian
ukuran dan byte dari memori baru yang ingin Anda alokasikan.
Jadi ini akan mengalokasikan jumlah memori yang Anda tentukan dengan
argumen kedua, itulah argumen kedua. Ini mentransfer konten memori yang dialokasikan sebelumnya,
yang direferensikan oleh pointer, sehingga secara otomatis mengetahui berapa banyak memori yang
telah Anda alokasikan sebelumnya karena Anda memasukkan pointer.
Dan kemudian itu benar-benar akan menambah itu, memori yang baru dialokasikan.
Dan itu mengembalikan pointer kosong ke memori baru.
Jadi Anda harus menyusunnya kembali ketika Anda memanggil realoc seperti yang lainnya.
Ini mengembalikan nol jika Anda tidak dapat mengalokasikan kembali, yang
lagi-lagi mungkin merupakan kesalahan fatal dan Anda harus membatalkannya.
Fitur yang paling penting dari operasi ini adalah
bahwa realoc mempertahankan isi dari area memori asli, Anda hanya memperluas memori itu.
Ini mungkin terfragmentasi karena Anda mungkin tidak dapat melakukannya secara berurutan, tetapi Anda
masih memiliki semua memori yang dapat Anda tetapkan untuk data sekarang.
Mari kita lihat sebuah contoh.
Dalam contoh ini, kita akan menggunakan malloc dan kemudian kita akan mengalokasikan kembali memori dan
kemudian kita akan membebaskannya.
Jadi di sini kita membuat penunjuk karakter.
Kami tidak menginisialisasi ke nol, kami mungkin seharusnya.
Tapi itu tidak memiliki memori yang dialokasikan untuk apa yang ditunjuknya.
Ini memiliki memori yang dialokasikan untuk
menyimpan pointer, yang hanya sebuah alamat. Tetapi jika Anda mencoba untuk pergi ke alamat itu, program Anda akan menjadi tuan rumah.
Jadi yang Anda lakukan adalah memanggil malloc.
Di sini kita mengatakan malloc 15.
Ini akan membuat 15 byte untuk penunjuk karakter.
Kami melemparkannya, karena mengembalikan pointer kosong. Jadi str adalah pointer
sekarang yang memiliki memori yang dialokasikan untuk apa yang ditunjuknya.
Kami kemudian dapat menggunakan str copy untuk meneruskan beberapa data ke apa yang
ditunjuknya, sebuah string dan
kami mencetak string di alamatnya.
Nah, kemudian kita menyadari bahwa apa yang kita alokasikan 15 byte
tidak cukup besar.
Jadi kemudian kami memanggil realloc, dan kami
memasukkan pointer yaitu str dan kami ingin mengalokasikan 25 byte lebih banyak dan kemudian
mengembalikan titik kosong karena kami harus membuangnya lagi.
Sekarang kita masih akan memiliki dalam memori Jason.
Jadi sekarang kita bisa memanggil string concatenated, dan kita menggabungkan string
com, jadi sekarang Jason. com dan kemudian kami mencetaknya.
Dan terakhir, namun tidak kalah pentingnya, mungkin hal
terpenting dari slide ini, jadi kita tidak memiliki kebocoran memori adalah kita menyebutnya bebas.
Selalu hubungi gratis saat Anda menelepon malloc.
Jadi mari kita lihat contoh ini di dalam blok kode.
Berikut contoh kode kami di dalam
editor blok kode kami.
Dan hal pertama yang harus Anda perhatikan
adalah kami menyertakan file header lib standar karena di situlah fungsi
malloc dan fungsi realoc kami serta fungsi gratis kami.
Juga karena kami menggunakan beberapa fungsi str, penggabungan dan
penyalinan, kami menyertakan string. H.
Sekarang pada baris delapan, kita akan membuat pointer karakter kita.
Tidak ada memori yang dialokasikan untuk itu.
Kita harus menginisialisasi ini ke null karena
belum menunjuk ke apa pun. Di jalur 11, kami memanggil malloc.
Dan kita mungkin harus mengatakan 15
kali ukuran char jika ukuran byte
char berbeda dan kemudian kita melemparkannya ke
penunjuk karakter
karena malloc mengembalikan kekosongan. Kami kemudian menyalinnya.
Jika kami mencoba menyalin ini dan kami tidak melakukan apa pun pada baris
11, program akan macet karena kami tidak memiliki memori yang dialokasikan untuk tujuan string apa.
Kami kemudian hanya mencetak string dan alamatnya.
Sekarang kita sebut realloc.
Kami perlu menyimpan lebih banyak data dari 15
byte, jadi kami akan mengalokasikan kembali dengan
25 byte dan kami mungkin ingin melakukan lagi sizeof char
agar konsisten.
Kami melemparkan ini dan kemudian kami menggabungkan ke lokasi memori kami
yang ada yang berisi jason. com, dan kami akan mencetak jason. com.
Dan terakhir, pada baris 20, kami membebaskan memori yang
sangat penting.
Jadi mari kita lanjutkan dan jalankan ini. Dan yang akan Anda lihat
adalah ketika kami mencetaknya untuk kedua kalinya, kami memiliki rangkaiannya.
Jadi string
pertama kami, kami memiliki memori yang dialokasikan dan itu adalah alamat 000C2918.
Kemudian kami membuat alamat baru dengan mengalokasikan kembali dan mengambil ukuran pointer yang ada yang
kami berikan sebagai argumen.
Jadi 000C0CD8 sebenarnya memiliki lebih banyak data yang dialokasikan
untuknya, data yang ada
dalam jason dan 25 byte lebih banyak.
Jadi yang Anda perhatikan adalah rangkaiannya berfungsi.
Karena ketika kita melakukan
realokasi, kita memasukkan isi jason ke dalam memori itu dan kita hanya memperpanjangnya.
Jadi banyak keuntungan menggunakan malloc ini, calloc ini dan panggilan realloc gratis.
Anda ingin menggunakan ini, Anda ingin memahami ini. Fungsi yang cukup sederhana untuk digunakan.
Jadi di slide terakhir kita, mari kita membahas beberapa panduan.
Anda ingin menghindari mengalokasikan banyak memori dalam jumlah kecil, itu tidak efisien.
Saat Anda mengalokasikan memori di
heap, itu memang memiliki beberapa overhead dengannya.
Dan jika Anda mengalokasikan blok kecil dari memori, itu akan memiliki lebih banyak overhead daripada mengalokasikan lebih
sedikit blok yang lebih besar.
Jadi alokasikan memori yang Anda butuhkan,
tetapi jangan lakukan setiap dua pernyataan dengan realokasi, lakukan potongan
besar.
Hanya bertahan pada memori selama Anda membutuhkannya. Memori adalah sumber daya yang langka.
Ketika di heap, itu bahkan lebih langka.
Jadi ketika Anda selesai dengan satu blok memori, telepon gratis.
Selalu pastikan bahwa Anda menyediakan untuk melepaskan memori yang telah Anda alokasikan, putuskan di mana
dalam kode Anda Anda akan melepaskan memori ketika Anda menulis kode yang mengalokasikannya.
Pastikan Anda memiliki akses ke penunjuk itu.
Jika Anda perlu membuat pointer menjadi global, maka Anda perlu melakukannya.
Tetapi biasanya di mana pun Anda mengalokasikan dalam fungsi itu, Anda harus melepaskannya di fungsi itu.
Jika Anda memiliki fungsi lain yang melepaskan
memori untuk Anda, Anda kemudian menganggap itu tidak baik. Ada terlalu banyak kopling dan dependensi di sana.
Orang yang membuatnya haruslah orang yang menghapusnya.
Jangan meletakkan tanggung jawab pada fungsi lain dan semacamnya.
Pastikan Anda tidak secara tidak sengaja menimpa alamat memori yang telah Anda alokasikan
di heap sebelum Anda merilisnya, ini akan menyebabkan kebocoran memori.
Jadi, jika Anda mencoba menulis terlalu banyak byte atau jika Anda memiliki kelebihan, Anda
mungkin mengalami masalah.
Jadi berhati-hatilah saat Anda mengalokasikan memori dalam satu lingkaran
karena ini dapat menyebabkan masalah dalam buffer overflows.
Saya harap ini membantu. Alokasi memori dinamis adalah masalah besar.
Saya akan memberi Anda tantangan yang membantu Anda menjadi lebih akrab dengan
ini, tetapi pastikan Anda memahami konsep ini. Terima kasih.