Berbagi teknologi

Belajar bahasa C dari awal 33 - Manajemen memori (1)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Situasi dasar
Manajemen memori bahasa C dibagi menjadi dua bagian: manajemen sistem dan manajemen manual pengguna pemrogram. Memori yang dikelola oleh sistem sebagian besar adalah variabel (variabel lokal) di dalam fungsi. Bagian dari variabel ini masuk ke memori ketika fungsi sedang berjalan. Bagian dari area memori ini menjadi "area tumpukan". , sistem operasi secara otomatis mengeluarkannya dari memori. Memori yang dikelola secara manual oleh pengguna sebagian besar berupa variabel (variabel global) yang ada di seluruh proses program yang berjalan. Area memori tempat bagian ini berada disebut "area heap". oleh pengguna. Jika Anda lupa melepaskannya setelah digunakan, itu akan tetap menempati memori hingga diserahkan ke sistem operasi saat program keluar.
2. penunjuk kosong
Ruang memori di komputer diberi kode alamat unik, dan area memori tertentu dapat ditemukan melalui penunjuk memori. Variabel penunjuk harus memiliki tipe, misalnya: int* p=&x; mendeklarasikan penunjuk bertipe int, yang menunjuk ke alamat variabel integer x. Ketika kompiler mendapatkan data dari alamat ini, ia mengetahui bahwa tipe int data disimpan. Ketika Anda tidak yakin jenis data apa yang disimpan dan hanya ingin mencari alamat memori blok terlebih dahulu, penunjuk tipe void digunakan. Penunjuk tipe kosong juga disebut penunjuk tipe tidak terbatas dan dapat menunjuk ke semua tipe data.
Pointer bertipe void dapat diubah menjadi pointer tipe lain, dan tidak ada yang istimewa dalam penggunaannya, kecuali konten yang disimpan tidak dapat diuraikan melalui metode "*".
int x = 10; //Deklarasikan variabel integer x
void* p = &x; //Deklarasikan pointer void dan arahkan ke alamat x, yang menunjukkan bahwa pointer int (&x) diubah menjadi pointer void.
int* q = p; // penunjuk kosong diubah kembali menjadi penunjuk bilangan bulat
printf("%dalam", *q ); //Hasil Jalankan: 10
Perhatikan perbedaan antara void* dan void: void tidak bertipe, dan ketika digunakan untuk mendeklarasikan suatu fungsi, artinya tidak ada nilai kembalian; sedangkan void*, meskipun tidak bertipe tetapi memiliki pointer, mengembalikan sesuatu.
3. Fungsi yang berhubungan dengan manajemen memori
1.malloc()
Fungsi ini dapat diingat secara terpisah. m adalah singkatan dari memori, dan alloc adalah singkatan dari alokasi. Bersama-sama keduanya mengalokasikan memori.
Fungsi: mengajukan blok memori berkelanjutan dari area heap (pengingat: memori area heap perlu dikelola oleh pemrogram dan harus dimusnahkan setelah digunakan. Ini harus selalu diingat format penggunaan: malloc (lihat 1);
Parameter: Parameter 1 adalah ukuran blok memori (integer non-negatif bertipe size_t, nilai kembalian sizeof bertipe ini)
Nilai yang dikembalikan: void* pointer (kita akan menggunakan jenis pointer apa pun yang kita gunakan untuk menerima memori yang dialokasikan)
Penggunaan: Variabel yang dideklarasikan menggunakan fungsi malloc berada di area heap, sehingga metode deklarasi anonim sering digunakan, yaitu, alih-alih menggunakan metode alamat variabel tertentu, malloc langsung mengembalikan pointer, seperti yang ditunjukkan di bawah ini:
int* ptr = (int*) malloc(sizeof(int)); //Variabel penunjuk int dideklarasikan di area heap
Konversi paksa dalam tanda kurung tidak diperlukan. malloc mengembalikan void*, yang dapat diterima dengan int*.
Tindakan pencegahan:
a.Gunakan fungsi malloc untuk memasukkan<stdlib.h>file header, seperti hanya berisi<stdio.h> Ini dikompilasi dengan baik tetapi tidak berjalan dengan benar, ingatlah itu.
b. Tetapkan nilai ke ptr: *ptr=1000;.
c.Gunakan malloc bersamaan dengan free (yang akan Anda temui nanti).
d. Malloc mungkin tidak berhasil dalam mengalokasikan alamat. Jika tidak berhasil, ia akan mengembalikan NULL. Oleh karena itu, pernyataan if dapat ditambahkan untuk diproses.
e. malloc hanya mengalokasikan memori, terlepas dari inisialisasi. Jika inisialisasi diperlukan, fungsi lain perlu dipanggil.
f. Kesempatan yang paling umum digunakan untuk malloc adalah mengalokasikan memori untuk array dan struktur data khusus.
2.memset()
Fungsi: Menetapkan nilai awal untuk setiap byte di blok memori yang ditunjuk oleh sebuah pointer.
Parameter: Parameter 1 Penunjuk menunjuk ke memori target Parameter 2 Konten penugasan (nilai kode ASCII tipe int atau karakter tipe char) Parameter 3 Jumlah byte yang akan ditetapkan (tipe size_t)
Nilai kembalian: Mengembalikan penunjuk yang diarahkan ke memori target. Tidak ada artinya menerima, sama seperti parameter 1.
Penggunaan: memset(ptrDestMem,'A',sizeof(char)*1024) //Menetapkan karakter A ke setiap byte blok memori dengan panjang 1024 byte
Tindakan pencegahan:
a. File header yang memiliki fungsi ini adalah<string.h> , beberapa kompiler dapat digunakan secara normal tanpa menyertakan file header ini. Jika terjadi kesalahan saat berjalan, harap sertakan.
b. Perhatikan bahwa memset adalah operasi pada byte (bukan bit); parameter 3 mengacu pada berapa banyak byte yang perlu ditetapkan, yang bisa kurang dari atau sama dengan jumlah byte dalam memori target, tetapi tidak boleh melebihi batas.
c.Nilai parameter 2 tidak boleh melebihi yang dapat ditampung oleh satu byte (int tipe 255).
2、gratis()
Fungsi: Fungsi yang dipasangkan dengan malloc, digunakan untuk melepaskan memori yang dialokasikan oleh fungsi malloc dan mencegah kebocoran memori
Parameter: pointer dikembalikan oleh fungsi malloc
Penggunaan: gratis(ptr);
Tindakan pencegahan:
a. File header yang perlu disertakan saat menggunakan gratis juga<stdlib.h> , jangan lupa.
b. Fungsi bebas hanya dapat dijalankan satu kali, dan alamat memori yang sama tidak dapat dilepaskan berulang kali, dan penunjuk yang dilepaskan tidak dapat digunakan lagi.
c. Sebaiknya tulis malloc dan free berpasangan terlebih dahulu, lalu masukkan kode lain di tengahnya agar tidak lupa.
3.alokasi ulang()
re, artinya lagi, singkatan alokasi alokasi, bersama-sama berarti alokasi ulang memori
Fungsi: Memodifikasi ukuran blok memori yang dialokasikan (menambah atau mengurangi).
Parameter: Parameter 1, penunjuk blok memori asli, parameter 2, ukuran blok memori setelah ditambah atau dikurangi (masih bertipe size_t)
Nilai yang dikembalikan: void* pointer (dapat diterima oleh variabel tipe pointer asli)
Penggunaan: void* newPtr=realloc(ptr,sizeof(int)*10);
Tindakan pencegahan:
a.Saat menggunakan fungsi realoc, fungsi ini juga perlu disertakan<stdlib.h> .
b. Blok memori yang ditunjuk oleh penunjuk asli telah digantikan oleh penunjuk baru, sehingga penunjuk barulah yang harus dibebaskan ketika program berakhir, dan penunjuk asli tidak perlu dibebaskan, jika tidak maka akan terjadi kesalahan operasi. terjadi.
c. realloc mungkin gagal mengalokasikan memori dan mengembalikan NULL jika gagal, jadi lebih baik menambahkan pernyataan if untuk mengatasinya.
4. Contoh penerapan

  1. #include<stdio.h>
  2. #include<stdlib.h> //malloc、free、realloc
  3. #include<string.h> //memset
  4. int main(void)
  5. {
  6. //A void指针的使用
  7. float PI = 3.14159;
  8. void* pPI = &PI;
  9. float r = 2.5;
  10. printf("半径2.5圆的面积:%fn", r * r * *(float*)pPI);//*(float*)pPI—pPI强转为float指针后再解出指向的值
  11. //B malloc、memset、free函数使用
  12. int n = 8;
  13. void* pMyMem = malloc(sizeof(char)*n); //char占1字节,malloc分派n字节的内存,返给void指针
  14. if (pMyMem == NULL)return 0; //若分派内存失败,程序结束
  15. void* myMem2=memset(pMyMem,'B',sizeof(char)*8); //对malloc分派的内存区块个字节都写入字符'B'。
  16. //并用myMem2接收返回的指针
  17. if (pMyMem == myMem2)printf("memset写入区块指针与其返回的指针相同n");
  18. char* transCh = pMyMem; //将void指针转成char型指针
  19. printf("显示写入内容:");
  20. for (int i = 0; i < n; i++)
  21. {
  22. printf("%c ", *transCh); //显示写入的字符
  23. transCh++;
  24. }
  25. printf("n");//换行
  26. free(pMyMem); //释放malloc函数分派的内存
  27. //free(ch); //只有malloc分派的内存才需要释放,且只释放一次(这里会报错)
  28. //C realloc、free函数的使用
  29. int* pMem = malloc(sizeof(int)*5);
  30. if (pMem == NULL)return 0;
  31. for (int i = 0; i < 5; i++) pMem[i] = (i+1)*10;
  32. for (int i = 0; i < 5; i++) printf("%i ", pMem[i]);
  33. printf("n重新增加分派内存后n");
  34. int* newpMem = realloc(pMem, sizeof(int) * 10);
  35. if (newpMem == NULL)return 0;
  36. for (int i = 0; i < 10; i++) newpMem[i] = (i + 1) * 10;
  37. for (int i = 0; i < 10; i++)printf("%i ", newpMem[i]);
  38. free(newpMem); //释放realloc的内存
  39. //free(pMem);//pMem已被重置,不能再释放,此语句会造成运行失败
  40. getchar(); //暂停屏幕
  41. return 0;
  42. }