ProgramlamaC++ geliştirici

C++'de 'placement new' nedir? Bu mekanizma ne amaçla ve nasıl kullanılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap

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:

  • Kendi allocator'larınızı uygulamanıza olanak tanır.
  • Yeni bellek tahsisi giderleri azalır.
  • Standart allocator'ı çağırmaz - bellek yönetimi üzerinde kontrol sağlar.

Bakan Sorusu

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!

Gerçek Hatalar Üzerine Örnekler


Hikaye

Yüksek trafikli bir sistemde geliştirici, malloc + placement new ile 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 new kullanı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 new kullanarak 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.