Ini adalah solusi C yang sangat umum saya gunakan untuk masalah yang mungkin bisa membantu. Tidak seperti VLA, VLA tidak menghadapi risiko praktis stack overflow dalam kasus patologis.
/// Used for frequent allocations where the common case generally allocates
/// a small amount of memory, at which point a heap allocation can be
/// avoided, but rare cases also need to be handled which may allocate a
/// substantial amount. Note that this structure is not safe to copy as
/// it could potentially invalidate the 'data' pointer. Its primary use
/// is just to allow the stack to be used in common cases.
struct FastMem
{
/// Stores raw bytes for fast access.
char fast_mem[512];
/// Points to 'fast_mem' if the data fits. Otherwise, it will point to a
/// dynamically allocated memory address.
void* data;
};
/// @return A pointer to a newly allocated memory block of the specified size.
/// If the memory fits in the specified fast memory structure, it will use that
/// instead of the heap.
void* fm_malloc(struct FastMem* mem, int size)
{
// Utilize the stack if the memory fits, otherwise malloc.
mem->data = (size < sizeof mem->fast_mem) ? mem->fast_mem: malloc(size);
return mem->data;
}
/// Frees the specified memory block if it has been allocated on the heap.
void fm_free(struct FastMem* mem)
{
// Free the memory if it was allocated dynamically with 'malloc'.
if (mem->data != mem->fast_mem)
free(mem->data);
mem->data = 0;
}
Untuk menggunakannya dalam kasus Anda:
struct FastMem fm;
// `result` will be allocated on the stack if 'len <= 512'.
char* result = fm_malloc(&fm, len);
// send result over network.
...
// this function will only do a heap deallocation if 'len > 512'.
fm_free(&fm, result);
Apa yang dilakukan dalam kasus di atas adalah menggunakan stack jika string cocok menjadi 512 byte atau kurang. Kalau tidak, ia menggunakan alokasi tumpukan. Ini dapat berguna jika, katakanlah, 99% dari waktu, string tersebut cocok menjadi 512 byte atau kurang. Namun, katakanlah ada beberapa kasus eksotis gila yang kadang-kadang Anda mungkin perlu menangani di mana string adalah 32 kilobyte di mana pengguna tertidur di keyboard-nya atau sesuatu seperti itu. Ini memungkinkan kedua situasi ditangani tanpa masalah.
Versi aktual yang saya gunakan dalam produksi juga memiliki versi sendiri realloc
dan calloc
dan seterusnya serta struktur data C ++ yang sesuai standar yang dibangun pada konsep yang sama, tetapi saya mengekstrak minimum yang diperlukan untuk menggambarkan konsep tersebut.
Memang ada peringatan bahwa itu berbahaya untuk disalin dan Anda tidak boleh mengembalikan pointer yang dialokasikan melaluinya (mereka bisa berakhir tidak valid karena FastMem
instance dihancurkan). Ini dimaksudkan untuk digunakan untuk kasus-kasus sederhana dalam lingkup fungsi lokal di mana Anda akan tergoda untuk selalu menggunakan stack / VLA sebaliknya jika beberapa kasus yang jarang terjadi dapat menyebabkan buffer / stack overflow. Ini bukan pengalokasi tujuan umum dan tidak boleh digunakan seperti itu.
Saya benar-benar menciptakannya beberapa waktu lalu sebagai tanggapan terhadap situasi dalam basis kode lama menggunakan C89 bahwa mantan tim berpikir tidak akan pernah terjadi di mana pengguna berhasil menamai item dengan nama yang lebih dari 2.047 karakter (mungkin dia tertidur di keyboard-nya) ). Rekan-rekan saya benar-benar mencoba untuk meningkatkan ukuran array yang dialokasikan di berbagai tempat menjadi 16.384 sebagai respons di mana saya pikir itu semakin konyol dan hanya menukar risiko stack overflow yang lebih besar dengan imbalan risiko buffer overflow yang lebih rendah. Ini memberikan solusi yang sangat mudah dipasang untuk memperbaiki kasus-kasus itu dengan hanya menambahkan beberapa baris kode. Hal ini memungkinkan kasus umum ditangani dengan sangat efisien dan masih menggunakan tumpukan tanpa kasus-kasus langka gila yang menuntut tumpukan perangkat lunak. Namun, saya telah menemukannya bermanfaat sejak saat itu bahkan setelah C99 karena VLA masih tidak dapat melindungi kita terhadap tumpukan berlebihan. Yang ini bisa tetapi masih menyatu dari tumpukan untuk permintaan alokasi kecil.