- Katılım
- 12 May 2026
- Mesajlar
- 87
- Tepkime puanı
- 130
GameServer çökme (crash) hatalarını kaynağından yakalamanın en etkili yolu
Sunucu bazen kendiliğinden çöküyor ve debugger seni STL'nin (mutex, vector, map) iç kodlarına atıyor. Örneğin:
Kod:
pMap = 0xdddddddddddddddd // silinmiş (freed) bellek
pMap = 0xffffffffffffff03 // çöp (garbage) değer
Bu değerler nullptr değildir, bu yüzden klasik kontrolün işe yaramaz:
Kod:
if (pMap == nullptr) // 0xdddddddd bunu GEÇER, sonra deref'te çöker!
Bu tam olarak bir "use-after-free" hatasıdır: bir nesne delete edilmiş ama pointer'ı hâlâ başka bir yerde kullanılıyor.
- PageHeap KAPALI: Bellek silinse bile hâlâ haritalı (mapped) kalır. Eski değeri okur, sessizce çalışır gibi görünür. Hata gizli kalır, saatler/günler sonra rastgele çöker.
- PageHeap AÇIK: Silinen blok anında "koruma sayfası"na (guard page) düşürülür. O belleğe ilk erişimde program hemen ve tam suç mahallinde çöker.
Kısaca: PageHeap sunucuyu "daha bozuk" yapmaz — hatayı geç değil, tam oluştuğu anda gösterir. Böylece gerçek suçluyu Call Stack'te net görürsün.
1. Application Verifier'ı Aç
- Başlat menüsünde "Application Verifier" ara ve yönetici olarak çalıştır. (Windows SDK ile gelir.)
- Sol üstte File → Add Application →
GameServer.exeseç. - Sağ panelde sadece Basics → Heaps işaretli kalsın (varsayılan yeterli).
- Save de ve kapat.
2. Debugger Altında Çalıştır
- Visual Studio'da projeyi Debug modda aç.
- F5 ile başlat. Hata oluştuğunda VS otomatik durur.
Alternatif (komut satırı):
Kapatmak için:Kod:gflags /p /enable GameServer.exe /full
Kod:gflags /p /disable GameServer.exe
Program durunca Call Stack (Çağrı Yığını) penceresini aç. STL/mutex iç fonksiyonlarını atla, ilk kendi kodun (GameServer) hangisiyse — gerçek suçlu odur.
PageHeap açıkken sunucu başlangıçta bir tablo yüklerken çöktü. Suç mahalli:
C++:
if (!m_pMap->PutData(pData->nBaseItemID, pData))
delete pData; // pData silindi
g_pMain->RightClickExchangeItemList.push_back(pData->nBaseItemID); // <-- SILINEN belleği okudu!
Tabloda aynı ID iki kez varsa
PutData false döner → delete pData çalışır → alt satır silinmiş belleği okur ve çöker.
C++:
uint32 nBaseItemID = pData->nBaseItemID; // önce kopyala
if (!m_pMap->PutData(nBaseItemID, pData))
{
delete pData; // duplicate: kaydı at
return true;
}
g_pMain->RightClickExchangeItemList.push_back(nBaseItemID); // güvenli
return true;
- nullptr kontrolü yetmez — freed/garbage değerler kontrolü geçer.
- PageHeap hatayı gizlenmeden, tam oluştuğu anda gösterir.
- Call Stack'te ilk kendi fonksiyonun = gerçek suçlu.
- "delete → sonra kullan" kalıbından kaçın; değeri önce kopyala.
Faydalı olması dileğiyle. Sorularınız için yorum bırakabilirsiniz.
Son düzenleme:
