C ++ char array [] kebocoran memori [duplikat]
saya membuat char arr [] dan menetapkannya string literal
char arr[] = "some string"; // arr occupies 12 chars in memory
std::cout << std::strlen(arr) << std::endl; // lenght is 11 chars + 1 null-terminator
//arr[11] is '\0'
selanjutnya saya memasukkan null-terminator menjadi 6 elemen
arr[5] = '\0';
std::cout << std::strlen(arr) << std::endl; // lenght is 5 chars + 1 null-terminator
- Apakah ini kebocoran memori?
- Bagaimana kompilator mengetahui bahwa ia harus membebaskan memori setelah '\ 0' pertama? (kapan akan menghapus variabel arr)
- Apakah mungkin untuk mengubah panjang variabel arr ini dan memberitahu compiler berapa banyak yang harus dikosongkan saat menghapus variabel?
Jawaban
- Apakah ini kebocoran memori?
Tidak.
- Bagaimana kompilator mengetahui bahwa ia harus membebaskan memori setelah '\ 0' pertama? (kapan akan menghapus variabel arr)
Variabelnya adalah 12 karakter. Ini sama dengan menulis:
char arr[12] = "some string";
Jadi itu akan selalu membebaskan 12 karakter. Variabelnya adalah array 12 karakter; fakta bahwa karakter ke-6 kebetulan adalah '\ 0' sama sekali tidak relevan.
Ngomong-ngomong, setelah Anda menyetel karakter ke-6 menjadi '\ 0', Anda masih diizinkan untuk menggunakan semua 12 karakter, karena itu masih berupa larik 12 karakter. Bahkan yang setelah '\ 0'. Tetapi Anda tidak dapat menyimpan 13 karakter di dalamnya.
- Apakah mungkin untuk mengubah panjang variabel arr ini dan memberitahu compiler berapa banyak yang harus dikosongkan saat menghapus variabel?
Tidak. Tidak mungkin mengubah ukuran variabel apa pun.
Dalam kode ini:
char arr[] = "some string";
variabelnya arr
adalah array statis dengan ukuran tetap. Tidak ada alokasi memori dinamis di sini, jadi tidak perlu khawatir tentang kebocoran memori. Kompilator akan mengurus memori, apa pun yang Anda tulis arr
.
Untuk kelengkapan.
Juga tidak ada kebocoran memori di memori yang dialokasikan, seperti di:
char* arr = (char*) malloc(12);
strcpy(arr, "some string");
arr[6] = '\0';
free(arr);
Manajemen memori berjalan dengan memori yang dialokasikan (12), bukan dengan penggunaan yang mendasarinya (karakter nul-terminated *). (Gaya C, C ++ juga)
Sepertinya Anda mendapatkannya mundur. Ukuran larik di C ++ tidak dapat diubah, titik. Karena fakta itu dan karena fakta bahwa jika Anda melewatkan array sebagai pointer Anda kehilangan informasi ukuran sebenarnya dari perjanjian array itu dibuat untuk string gaya C - 0 byte alias \0
terminator nol yang diperlakukan sebagai akhir dinamis dari string. Perjanjian berarti bahwa fungsi yang bekerja dengan string gaya C memperlakukannya sebagai penghentian string. Itu memungkinkan Anda menggunakan larik ukuran tetap untuk string dengan panjang berbeda dan hanya meneruskan satu penunjuk tanpa ukuran memori aktual ke fungsi untuk membacanya (misalnya cetak ke layar). Perhatikan, ketika Anda meneruskan char array ke fungsi yang menulis data ke dalamnya, Anda sering perlu memberi tahu apa itu ukuran array sebenarnya , sehingga fungsi itu tidak akan mengakses memori di luar batas karena fungsi tersebut akan mengabaikan terminator null jika sudah ada.
Itu saja, perjanjian ini terjadi pada lapisan berbeda yang dikelola array. Jadi, data apa pun yang Anda masukkan ke dalam array itu tidak akan memengaruhi ukurannya dari sudut pandang bahasa, untuk kompiler C ++ Anda membuat array ukuran tetap, Anda memasukkan beberapa data ke dalamnya dan ketika masa pakainya tiba, kompiler menghancurkannya sebagai array ukuran tetap secara keseluruhan. Tidak peduli jika Anda meletakkan nol byte di sana atau tidak.
Kebocoran memori terjadi ketika memori dialokasikan oleh pemrogram menggunakan operator new
dan tidak dihapus menggunakan operator delete
atau delete []
.
Dalam deklarasi ini
char arr[] = "some string";
Ini adalah kompilator (atau sistem) mengalokasikan memori untuk array array karakter yang memiliki baik durasi penyimpanan otomatis atau durasi penyimpanan statis. Jadi kompilator (atau sistem) bertanggung jawab untuk membebaskan memori yang dialokasikan. Alamat dari memori yang dialokasikan diketahui oleh kompilator (atau sistem).
Menggunakan pernyataan ini
arr[5] = '\0';
Anda tidak mengalokasikan kembali array tersebut. Anda baru saja mengubah isinya lebih tepatnya hanya satu byte-nya.
Bagaimana kompilator mengetahui bahwa ia harus membebaskan memori setelah '\ 0' pertama? (kapan akan menghapus variabel arr)
Karena kompilator (atau sistem) mengetahui bagaimana objek tipe array dideklarasikan.
Untuk objek dialokasikan 12 byte.
char arr[] = "some string";
Apakah mungkin untuk mengubah panjang variabel arr ini dan memberitahu compiler berapa banyak yang harus dikosongkan saat menghapus variabel?
Saya pikir yang Anda maksud adalah ukuran benda. Tidak, Anda tidak dapat mengubah ukuran objek karena bukan Anda yang mengalokasikan memori untuk objek tersebut.
Anda dapat mengalokasikan kembali objek tersebut jika Anda menggunakan operator new
untuk mengalokasikannya sebagai contoh
char *arr = new char[12];
std::strcpy( arr, "some string" );
//...
char *tmp = new char[20];
strcpy( tmp, "another " );
strcat( tmp, arr );
delete [] arr;
arr = tmp;