- Mesaj
- 42
- Çözümler
- 1
- Beğeni
- 124
- Puan
- 699
- Ticaret Puanı
- 0
Metin2 source çöplüğünde gözüme takılması üzerine;
C++'da user-declared dtor yazarsanız (kaynak yöneten sınıflarda genelde yazarsınız) derleyici copy ctor ve copy assign operatorunu implicitly declare eder.
`TEMP_BUFFER` bir kaynak yönetiyor (has-a LPBUFFER), destructorunda kaynağı geri veriyor (RAII olarak bilinen, Bjarne tarafından uydurulmuş idiom).
Ama kaynak yöneten bir sınıfınız varsa ve derleyicinin yazdığı copy special member funclarını kullanırsanız senaryoya bağlı olarak başınıza farklı işler gelebilir.
Bİzim durumumuz için varsayalım ki;
gibi bir kod yazdınız; derleyicinin ürettiği copy-assign shallow copy yapar, b1'in eski buffer'ı dtoru görmeden (yani buffer_delete çağrılmadan) üstüne b2.buf yazılır. b1.buf == b2.buf olduğu için copy-ctor'da oluşacak corruption da meydana gelir. Yani assign = leak + corruption.
Copy-ctor'da gördüğüm kadarıyla sadece corruption var. İki nesne aynı `buf`'ı paylaşır, dtorda `buf` iki kez `buffer_delete`'e gider. `buffer_delete` eğer boyut poole sığıyorsa `free` çağırmıyor, buffer'ı free liste geri koyuyor. Aynı `buf` listeye iki kez push edilince mantıken `buf->next = buf` olur, yani next node aslında kendine işaret ediyor. Sonra `buffer_new` aynı `buf`'ı iki ayrı çağrıya dağıtır olası olarak heap overflow, infinite loop tarzı bir şey yaşanabilir. Klasik corruption, alakasız bir yerde patlar diye tahmin ediyorum.
En basit çözüm copy-ctor ve copy-assign operatoru explicit olarak delete etmek amaç önlem almak, zaten aklı başında kimsenin TEMP_BUFFER'ı kopyalayacağını sanmıyorum.
yok ben illa rule of five'a uyucam diyorsanız:
Notlar:
-> bu deep copy sadece yazılmış veriyi taşır, read_point ve flag kopyalanmaz, yani yarı okunmuş bir buffer'ın tam state'ini korumaz. Paket kurmada yazma için kullanıldığından sorun değil, ama bunu bilerek kullanın.
-> dediğim gibi hayati bir şey değil büyük ihtimalla buffer'ı hiç kopyalamamışsınızdır ama benzer diğer kaynak yöneten classlarda da benzer durumları göz önünde bulundurun.
-> lütfen yapay zeka ile oluşturulan yorumlar atmayın
-> UDC'ler tamamen örnek implementasyon, dilerseniz copy-swap idiom gibi tkeniklerde kullanabilirsiniz.
Tek uyarı: user-declared dtor olduğunda move ctor ve move assign operator derleyici tarafından implicitly declare edilmez, yani copy'leri delete edince class non-moveable hale gelir. Buffer'ı `std::move`'layan bir yerde kullanırsanız (fluent api gibi) move ctor/assign'ı user-declared yazmanız gerekir ki örnek olarak yukarıda yazdım, siz yine de kullanmadan göz atın buffer logice gözümden kaçan yerler olabilir, varsa yorumda belirtirseniz düzeltiriz. Salt önlem için copy-delete yeter ama ben olsam daha makul modern bir buffer mekanizması yazardım.
mock:
İyi forumlar.
C++'da user-declared dtor yazarsanız (kaynak yöneten sınıflarda genelde yazarsınız) derleyici copy ctor ve copy assign operatorunu implicitly declare eder.
`TEMP_BUFFER` bir kaynak yönetiyor (has-a LPBUFFER), destructorunda kaynağı geri veriyor (RAII olarak bilinen, Bjarne tarafından uydurulmuş idiom).
Ama kaynak yöneten bir sınıfınız varsa ve derleyicinin yazdığı copy special member funclarını kullanırsanız senaryoya bağlı olarak başınıza farklı işler gelebilir.
Bİzim durumumuz için varsayalım ki;
C++:
TEMP_BUFFER b1, b2;
b1 = b2;
gibi bir kod yazdınız; derleyicinin ürettiği copy-assign shallow copy yapar, b1'in eski buffer'ı dtoru görmeden (yani buffer_delete çağrılmadan) üstüne b2.buf yazılır. b1.buf == b2.buf olduğu için copy-ctor'da oluşacak corruption da meydana gelir. Yani assign = leak + corruption.
Copy-ctor'da gördüğüm kadarıyla sadece corruption var. İki nesne aynı `buf`'ı paylaşır, dtorda `buf` iki kez `buffer_delete`'e gider. `buffer_delete` eğer boyut poole sığıyorsa `free` çağırmıyor, buffer'ı free liste geri koyuyor. Aynı `buf` listeye iki kez push edilince mantıken `buf->next = buf` olur, yani next node aslında kendine işaret ediyor. Sonra `buffer_new` aynı `buf`'ı iki ayrı çağrıya dağıtır olası olarak heap overflow, infinite loop tarzı bir şey yaşanabilir. Klasik corruption, alakasız bir yerde patlar diye tahmin ediyorum.
En basit çözüm copy-ctor ve copy-assign operatoru explicit olarak delete etmek amaç önlem almak, zaten aklı başında kimsenin TEMP_BUFFER'ı kopyalayacağını sanmıyorum.
Burayı görüntülemek için üye girişi yapmalı veya kayıt olmalısınız.
yok ben illa rule of five'a uyucam diyorsanız:
Burayı görüntülemek için üye girişi yapmalı veya kayıt olmalısınız.
Notlar:
-> bu deep copy sadece yazılmış veriyi taşır, read_point ve flag kopyalanmaz, yani yarı okunmuş bir buffer'ın tam state'ini korumaz. Paket kurmada yazma için kullanıldığından sorun değil, ama bunu bilerek kullanın.
-> dediğim gibi hayati bir şey değil büyük ihtimalla buffer'ı hiç kopyalamamışsınızdır ama benzer diğer kaynak yöneten classlarda da benzer durumları göz önünde bulundurun.
-> lütfen yapay zeka ile oluşturulan yorumlar atmayın
-> UDC'ler tamamen örnek implementasyon, dilerseniz copy-swap idiom gibi tkeniklerde kullanabilirsiniz.
Tek uyarı: user-declared dtor olduğunda move ctor ve move assign operator derleyici tarafından implicitly declare edilmez, yani copy'leri delete edince class non-moveable hale gelir. Buffer'ı `std::move`'layan bir yerde kullanırsanız (fluent api gibi) move ctor/assign'ı user-declared yazmanız gerekir ki örnek olarak yukarıda yazdım, siz yine de kullanmadan göz atın buffer logice gözümden kaçan yerler olabilir, varsa yorumda belirtirseniz düzeltiriz. Salt önlem için copy-delete yeter ama ben olsam daha makul modern bir buffer mekanizması yazardım.
mock:
Burayı görüntülemek için üye girişi yapmalı veya kayıt olmalısınız.
İyi forumlar.
manuel yönetim takibi yapmak ayar ediyor beni. Ayrıca bu sıkıntı sadece TEMP_BUFFER a özgü değil, client tarafında bile çok fazla buna benzer senaryolar var