Not : Bu yazıyla ilgili olarak IPC (Inter Process Communication) ve Segmentation Fault başlıklı yazılara göz atabilirsiniz.
Heap ve Threadler
Heap, uygulama içindeki tüm threadler tarafından paylaşılır. Heap parçalandıkça (fragmentation), allocator talep edilen alanı bulmak için daha fazla işlemci harcamak zorunda kalabilir. Bu yüzden emniyet kritik (safety critical) uygulamalarda dinamik bellek kullanımı yasaklanmıştır. Daha fazla bilgi aşağıdaki için DO-178B başlıklı bölüme bakabilirsiniz.
kalloc()
Linux kernel'in kodlarında bellek ayırmak için kullanılır.
malloc()
malloc() ile mmap() birbirlerine çok benziyorlar. Her ikisi de sanal bir adres döndürüyor. heap management başlıklı soruda glibc dışında alternatif olarak kullanılabilecek başka heap kütüphaneleri de örnek olarak verilmiş durumda. Örneğin TCMalloc google tarafından kullanılıyor.
malloc işletim sisteminden sayfa istemek için Unix ve türevlerinde sbrk(), geri vermek için ise brk() sistem çağrılarını kullanır.
$ LD_PRELOAD="/usr/lib/libtcmalloc.so"yaparak yeniden derlemeye ihtiyaç duymadan kullanılabilir.
malloc void* döner, C dilinde bu belleği kendi değişkenimize atarken, cast yapılmaması gerekir. Yani aşağıdaki kullanım doğru değil!
calloc()
Bu metod malloc ile aynı, sadece sıfır ile doldurulmuş bir hafıza döndürüyor.
realloc()
Bu metodun açıklaması burada. Yeni bir bellek alanı döndürüyor, eski bilgilerin sığdığı kadarını da kopyalıyor. malloc gerekenden biraz daha fazla alan ayırmışsa ve realloc bu alana sığıyorsa aynı alanı bellek alanını da döndürebilir.
new()
Bu metodun 3 tane overload edilmiş hali var.
Yani ::operator new (10); kullanımı ile de malloc gibi bellek ayırabiliriz.
exception atmayan new
Eğer new'in exception atmayıp NULL döndüren versiyonunu çağırmak istersek aşağıdaki gibi yapmalıyız.
nothrow new dosyasında tanımlı boş bir sınıf. Örnek:
placement new
Mevcut bir belleği kullanarak nesne yaratma anlamına geliyor.
Aşağıda placement new için örnek var.
Bir başka örnekte ise normal ve placement new arasındaki fark gösterilmiş.
placement delete
Böyle bir operator yok!. Dolayısıyla placement new ile yaratılan nesnenin destructor'ını elle çağırmak gerekir. delete veya delete[] kullanılmamalı!
kendi new operatörümüz
operator new()'i override etmek için tek yapmamız gereken buradaki metod imzalarından farklı metodlar yaratmak.
Buradaki soruda benzer bir açıklama var.
#define MY_NEW (CONSTRUCTOR) (new (__FILE__,__LINE__) CONSTRUCTOR)
void* operator new (size_t sizeInBytes,const char* file,int line){
void* buffer = //get from pool
return buffer;
}
delete
delete veya delete[] eğer silinen şey bir nesne ise yani POD değilse, nesnenin destructor'ının çağırılmasını sağlar.
DO1-78B ve Dinamik Bellek Kullanımı
Buradaki yazıda dinamik bellek kullanımını kontrol etmek için bellek ayıran metodların override edildiği anlatılmış.
Bazen bellek adresinin belli bir sayının katı olması istenir. Bu durumda posix_memalign() kullanılabilir. Örneğin posix_memalign(&p, 32, 128) 128 byte büyüklüğünde ve başlangıç adresi 32'nin katı olan bir bellek alanı döner. Linux'ta memalign posix_memalign ile aynı işi yapar.
Bu metodun Windows'taki karşılığı _aligned_malloc() metodudur.
Aşağıdaki metodu her ikisinde de çalışır.
Bazen de bellek alanının belli bir sayının katı olması istenir. Bu durumla ilgili olarak Data Alignment başlıklı yazıya bakabilirsiniz.
Heap ve Threadler
Heap, uygulama içindeki tüm threadler tarafından paylaşılır. Heap parçalandıkça (fragmentation), allocator talep edilen alanı bulmak için daha fazla işlemci harcamak zorunda kalabilir. Bu yüzden emniyet kritik (safety critical) uygulamalarda dinamik bellek kullanımı yasaklanmıştır. Daha fazla bilgi aşağıdaki için DO-178B başlıklı bölüme bakabilirsiniz.
kalloc()
Linux kernel'in kodlarında bellek ayırmak için kullanılır.
malloc()
malloc() ile mmap() birbirlerine çok benziyorlar. Her ikisi de sanal bir adres döndürüyor. heap management başlıklı soruda glibc dışında alternatif olarak kullanılabilecek başka heap kütüphaneleri de örnek olarak verilmiş durumda. Örneğin TCMalloc google tarafından kullanılıyor.
malloc işletim sisteminden sayfa istemek için Unix ve türevlerinde sbrk(), geri vermek için ise brk() sistem çağrılarını kullanır.
$ LD_PRELOAD="/usr/lib/libtcmalloc.so"yaparak yeniden derlemeye ihtiyaç duymadan kullanılabilir.
malloc void* döner, C dilinde bu belleği kendi değişkenimize atarken, cast yapılmaması gerekir. Yani aşağıdaki kullanım doğru değil!
int *ptr = (int *)malloc(10 * sizeof (*ptr));malloc döndürdüğü bellek alanının önündeki byte'lara bellek yönetimiyle ilgili bazı bilgileri ekler.
calloc()
Bu metod malloc ile aynı, sadece sıfır ile doldurulmuş bir hafıza döndürüyor.
realloc()
Bu metodun açıklaması burada. Yeni bir bellek alanı döndürüyor, eski bilgilerin sığdığı kadarını da kopyalıyor. malloc gerekenden biraz daha fazla alan ayırmışsa ve realloc bu alana sığıyorsa aynı alanı bellek alanını da döndürebilir.
new()
Bu metodun 3 tane overload edilmiş hali var.
new A();şeklinde bir kod yazılınca, derleyici önce
::operator new (sizeof(A));ile aynı malloc'taki gibi bellek alanı ayıran kod parçasını, daha sonra da A nesnesinin constructor metodunu çağıran kod parçasını üretiyor. Aşağıdaki örnekte derleyicinin ürettiği kodu görebiliriz.
Yani ::operator new (10); kullanımı ile de malloc gibi bellek ayırabiliriz.
exception atmayan new
Eğer new'in exception atmayıp NULL döndüren versiyonunu çağırmak istersek aşağıdaki gibi yapmalıyız.
nothrow new dosyasında tanımlı boş bir sınıf. Örnek:
placement new
Mevcut bir belleği kullanarak nesne yaratma anlamına geliyor.
Aşağıda placement new için örnek var.
Bir başka örnekte ise normal ve placement new arasındaki fark gösterilmiş.
placement delete
Böyle bir operator yok!. Dolayısıyla placement new ile yaratılan nesnenin destructor'ını elle çağırmak gerekir. delete veya delete[] kullanılmamalı!
kendi new operatörümüz
operator new()'i override etmek için tek yapmamız gereken buradaki metod imzalarından farklı metodlar yaratmak.
Buradaki soruda benzer bir açıklama var.
There is really no such thing as “overriding” global operator new. You can overload it by supplying a function which takes additional arguments beyond the required size_t first argument, and you can provide a class with its own operator new.Aşağıda macro kullanarak kendi new operatörümüzü çağırma örneği var.
#define MY_NEW (CONSTRUCTOR) (new (__FILE__,__LINE__) CONSTRUCTOR)
void* operator new (size_t sizeInBytes,const char* file,int line){
void* buffer = //get from pool
return buffer;
}
delete
delete veya delete[] eğer silinen şey bir nesne ise yani POD değilse, nesnenin destructor'ının çağırılmasını sağlar.
DO1-78B ve Dinamik Bellek Kullanımı
Buradaki yazıda dinamik bellek kullanımını kontrol etmek için bellek ayıran metodların override edildiği anlatılmış.
Developers can head off risks by taking away responsibility for memory management in safety-critical tasks from malloc and free and assigning it to the application. The developer replaces the standard allocator with a custom allocator that sets aside a buffer for the exclusive use of that task, and satisfies all memory allocation requests out of that buffer. If the memory reserved for this buffer is exhausted, the application is informed, and can then free up memory within the buffer or find more memory to devote to the task. Exhausting the memory in this dedicated pool has no impact on other parts of the system.Memory Alignment
Bazen bellek adresinin belli bir sayının katı olması istenir. Bu durumda posix_memalign() kullanılabilir. Örneğin posix_memalign(&p, 32, 128) 128 byte büyüklüğünde ve başlangıç adresi 32'nin katı olan bir bellek alanı döner. Linux'ta memalign posix_memalign ile aynı işi yapar.
Bu metodun Windows'taki karşılığı _aligned_malloc() metodudur.
Aşağıdaki metodu her ikisinde de çalışır.
#if defined(_WIN32)
return _aligned_malloc(m_Size, m_Alignment);
#else
void* mem;
int rs = posix_memalign(&mem, m_Alignment, m_Size);
return rs == EOK ? mem : NULL;
#endif
Bazen de bellek alanının belli bir sayının katı olması istenir. Bu durumla ilgili olarak Data Alignment başlıklı yazıya bakabilirsiniz.
Hiç yorum yok:
Yorum Gönder