placement new, C++'deki new operatörünün özel bir biçimidir. Zaten tahsis edilmiş bir bellek alanında belirli bir adreste bir nesne yerleştirmeye olanak tanır. Genellikle bellek yönetimini elle kontrol etmek için kullanılır ve allocator'ların, nesne havuzlarının ve sabit tamponlarda serileştirme işlemlerinin temelini oluşturur.
Sözdizimi:
#include <new> void* memory = malloc(sizeof(MyClass)); MyClass* obj = new (memory) MyClass(args...); // memory adresinde yapıcıyı çağırır
Burada bellek ayrı olarak tahsis edilir (örneğin, malloc veya bir allocator aracılığıyla) ve ardından sınıfın yapıcısı bu bellekte çağrılır. Dışarıdan silici çağırmayı unutmayın:
obj->~MyClass(); free(memory);
Artılar:
Aynı bellek bloğu 'placement new' kullanarak ardışık olarak birden fazla nesne için kullanılabilir mi ve bu ne gibi sonuçlara yol açar?
Sık karşılaşılan yanlış cevap - eski nesnenin durumu hakkında endişelenmeden bellek içinde yeni nesneleri yerleştirebilirsiniz. Aslında, eğer yeni bir nesne eski nesnenin üzerine yerleştirilirse ve silici çağrılmazsa, kaynak sızıntısı gerçekleşir ve silicinin çağrılması daha sonra UB'ye yol açar.
Örnek:
void* place = malloc(sizeof(A)); A* a = new (place) A(); B* b = new (place) B(); // A nesnesi yok edilmedi! UB!
Hikaye
Yüksek trafikli bir sistemde geliştirici,
malloc+placement newile bir nesne havuzu uyguladı, ancak nesneyi havuza dönerken silici çağırmayı unuttu. Sonuç olarak, kaynaklar (içindeki sistem tanıtıcıları) serbest bırakılmadı ve bellek sızıntıları ile sunucuların "donmasına" neden oldu.
Hikaye
İkili verilerin serileştirilmesi projesinde, nesneleri yerinde kodlamak için bir tampon ve
placement newkullanıldı. Ancak, yerleştirmeden önce belleği sıfırlarla başlatmayı unuttular, bu da başlatılmamış verilerin okunmasına ve POD yapıları ile çalışma sırasında tuhaf hatalara yol açtı.
Hikaye
Modüllerden biri, önceden tahsis edilmiş bir blok içinde
placement newkullanarak nesne dizilerini yerleştirmeye geçiş yaptı. Sınıfa yeni, karmaşık silicilere sahip üyeler eklendiğinde programın çökmesine neden olan sorunlar ortaya çıktı - her elemanı temizlerken her bir siliciyi açıkça çağırmayı unuttular, bu daha önce gerekmezdi.