Öncelikle, bunun mutlak bir cevabı olan mükemmel bir soru-cevap tarzı bir soru olmadığını fark ettim, ancak daha iyi çalışmasını sağlamak için herhangi bir ifade düşünemiyorum. Bunun mutlak bir çözüm olduğunu sanmıyorum ve bu, Stack Overflow yerine buraya göndermemin nedenlerinden biri.
Geçen ay boyunca, oldukça eski bir sunucu kodu (mmorpg) parçasını daha modern ve genişletilmesi / mod olması için yeniden yazıyordum. Ağ bölümü ile başladım ve benim için işleri yürütmek için bir 3. parti kütüphane (libevent) uyguladı. Tüm yeniden faktoring ve kod değişiklikleriyle bir yerde hafıza bozulmasına neden oldum ve nerede olduğunu bulmakta zorlanıyorum.
Bazı yükleri simüle etmek için ilkel botlar uygularken bile, çarpışmalara neden olamayacağım (bazı şeylere neden olan bir sorun çözdüm)
Şimdiye kadar denedim:
Bu cehennemden kurtulmak - Bir şey çökene kadar geçersiz bir yazı yazmaz (üretimde 1+ gün alabilir .. ya da sadece bir saat) bu beni gerçekten şaşırtıyor, kesinlikle bir noktada geçersiz belleğe erişir ve üzerine yazmaz şans mı? (Adres aralığını "yaymanın" bir yolu var mı?)
Kod Analizi araçları, yani kapsam ve kısaltma. Bazılarına işaret ettikleri halde .. kodda belirsizlik ve ileri vakalar ciddi bir şey yoktu.
İşlem gdb ile çökene kadar (undodb üzerinden) kayıt ve sonra geriye doğru çalışıyorum. Bu / sesler / olması gerektiği gibi olabilir, ancak ya otomatik tamamlama özelliğini kullanarak gdb'yi çökertiriyorum ya da çok fazla olası dal olduğundan (bir başkasının bozulmasına neden olan bir bozulma olduğu için) kaybolan bazı iç serbest yapıya giriyorum. ) üzerinde. Sanırım başlangıçta hangi göstergenin nereye tahsis edildiğine, hangi dallanma sorununu ortadan kaldıracağını görebilseydim iyi olurdu. Valgrind'i undodb ile çalıştıramıyorum ve normal gdb kaydı kullanışsız yavaş (eğer bu valgrind ile birlikte çalışıyorsa).
Kod incelemesi! Kendi başıma (iyice) ve bazı arkadaşlarımın kodumu gözden geçirmesine rağmen, yeterince iyiydi. Benimle bir kod inceleme / hata ayıklama yapmak için bir dev işe almayı düşünüyordum, ama çok fazla para harcayamayacağım ve az için çalışmaya istekli birini nerede arayacağımı bilemedim. konuyu bulamazsa veya hiç kimseyi nitelikli bulmazsa para.
Ayrıca şunu not etmeliyim: Genellikle tutarlı geri dönüşler alıyorum. Çarpmanın gerçekleştiği, çoğu zaman soket sınıfının bir şekilde bozulmuş olmasıyla ilgili birkaç yer var. Soket olmayan bir şeye işaret eden geçersiz bir işaretçi mi yoksa soket sınıfının kendisi (kısmen?) Anlamsızca yazılmaya başlıyor. Orada en çok kullanılanlardan biri olduğundan şüphelenmeme rağmen, en çok kullanılan kısımlardan biri, bu yüzden kullanılan ilk bozuk hafıza.
Bütün bu meselede yaklaşık 2 aydır beni meşgul etti (açık ve kapalı, daha fazla hobi projesi) ve huysuz IRL olduğum ve sadece pes etmeyi düşündüğüm noktaya gelmek beni gerçekten sinirlendiriyor. Sadece konuyu bulmak için ne yapmam gerektiğini düşünemiyorum.
Kaçırdığım faydalı teknikler var mı? Bununla nasıl başa çıkıyorsun? (Bu konuda çok fazla bilgi olmadığı için bu kadar yaygın olamaz .. ya da sadece gerçekten körüm?)
Düzenle:
Önemli olması durumunda bazı görüşler:
C ++ (11) kullanarak gcc 4.7 (debian wheezy tarafından sağlanan sürüm)
Kod temeli yaklaşık 150k satırdır.
David.pfx yayınına yanıt olarak düzenle: (yavaş yanıt için özür dilerim)
Örüntü aramak için çarpışmaların dikkatli kayıtlarını tutuyor musunuz?
Evet, hala etrafta yatan son kazaların dökümü var.
Birkaç yer gerçekten benzer mi? Ne şekilde
Eh, en son sürümde (kod eklediğim / kaldırdığımda veya ilgili yapıları değiştirdiğimde her şey değişiyor gibi görünüyor), her zaman bir öğe zamanlayıcı yönteminde yakalanır. Temel olarak bir öğenin süresi dolduktan sonra belirli bir süresi vardır ve müşteriye güncellenmiş bilgileri gönderir. Geçersiz soket işaretçisi (söyleyebildiğim kadarıyla hala geçerli) Player sınıfında, çoğunlukla bununla ilişkili olacaktı. Ayrıca, temizlik aşamasında, açıkça tahrip edilmemiş tüm statik sınıfları tahrip ettiği normal __run_exit_handlers
geri çekilmeden sonra (geriye dönük olarak) bir sürü çarpışma yaşıyorum . Çoğunlukla std::map
bir sınıfa dahil olmak, sanırım ilk ortaya çıkan şey bu.
Bozuk veriler neye benziyor? Sıfırları? Ascii? Desenler?
Henüz herhangi bir kalıp bulamadım, bana biraz rastgele görünüyor. Yolsuzluğun nerede başladığını bilmediğimden söylemek zor.
Öbekle ilgili mi?
Tamamen yığınla ilgili (Gcc'nin yığın korumasını etkinleştirdim ve hiçbir şey yakalamadım).
Yolsuzluktan sonra meydana geliyor
free()
mu?
Bu konuda biraz detaylandırmanız gerekecek. Etrafta serbestçe duran nesnelerin işaretçilerine sahip olmak mı demek istiyorsun? Nesne imha edildikten sonra her referansı boş bırakıyorum, bu yüzden bir şeyi kaçırmamışsam hayır. Bu olmasa da valgrind'da ortaya çıkmalı.
Ağ trafiği hakkında farklı bir şey var mı (arabellek boyutu, kurtarma döngüsü)?
Ağ trafiği ham verilerden oluşur. Böylece char dizileri, (u) intX_t veya daha karmaşık şeyler için paketlenmiş (dolguyu çıkarmak için) yapılar, her paket bir kimliği ve paket boyutunun kendisinden beklenen boyuta göre doğrulanmış bir başlıktan oluşur. Birkaç Mb boyutunda olan en büyük (dahili 'bootup' paketi, başlangıçta bir kez ateşlenmiş) sahip yaklaşık 10-60 bayttır.
Çok ve çok sayıda üretim iddiası var. Hasar yayılmadan önce erken ve öngörülebilir şekilde çarpın.
Bir zamanlar std::map
yolsuzlukla ilgili bir çöküş yaşadım , her varlığın “manzarasının” bir haritası vardı, onu görebilen her varlık var ve bunun tersi de var. Önüne 200 baytlık bir tampon ekledim ve sonra 0x33 ile doldurdum ve her erişimden önce kontrol ettim. Yolsuzluk sadece sihirli bir şekilde ortadan kayboldu, etrafta başka bir şeyi bozan bir şey taşımış olmalıyım.
Stratejik günlüğe kaydetme, yani tam olarak ne olduğunu tam olarak bilirsiniz. Bir cevaplamaya yaklaştıkça günlüklüğe ekleyin.
Uzatır .. çalışır.
Çaresizlik içinde, durumu kaydedebilir ve otomatik yeniden başlatabilir misiniz? Bunu yapan birkaç üretim yazılımını düşünebilirim.
Bunu biraz yapıyorum. Yazılım, ana bir "önbellek" işleminden ve bir şeyler almak ve kaydetmek için önbelleğe erişen diğer çalışanlardan oluşur. Bu yüzden kaza başına çok fazla ilerleme kaydetmiyorum, yine de tüm kullanıcıların bağlantısını keser ve bu kesinlikle bir çözüm değil.
Eşzamanlılık: iş parçacığı, yarış koşulları, vb
"Eşzamansız" sorguları yapmak için bir mysql dizisi var, her şey dokunulmamış olsa da ve sadece tüm kilidi olan işlevler aracılığıyla veri tabanı sınıfına bilgi paylaşıyor.
Kesmeler
30 saniye boyunca bir döngüyü tamamlamaması durumunda iptal eden, kilitlenmesini önlemek için bir kesme zamanlayıcısı vardır, ancak bu kod güvenli olmalıdır:
if (!tics) {
abort();
} else
tics = 0;
volatile int tics = 0;
Her döngü tamamlandığında tikler artar. Eski kod da.
olaylar / geri aramalar / istisnalar: durumu veya yığını önceden tahmin edilemez bir şekilde bozma
Çok sayıda geri arama kullanılıyor (zaman uyumsuz ağ G / Ç, zamanlayıcılar), ancak kötü bir şey yapmamaları gerekiyor.
Olağandışı veri: olağandışı giriş verileri / zamanlama / durum
Bununla ilgili birkaç ileri dava yaşadım. Paketler hala işlenirken bir soketin çıkarılması, bir nullptr'ye ve bunun gibi sonuçlara erişilmesine neden oldu; (Yıkımın kendisi, yıkılan tüm nesneleri her döngüde silen bir döngü tarafından gerçekleştirilir)
Eşzamansız bir harici sürece bağımlılık.
Detaylandırmak ister misiniz? Bu durum biraz yukarıda, yukarıda belirtilen önbellek işlemidir. Kafamın üstünden hayal edebileceğim tek şey, yeterince hızlı bir şekilde bitirememesi ve çöp verilerini kullanmaması olabilirdi, ancak bu, ağ kullandığı için de geçerli değil. Aynı paket model.
/analyze
) ve Apple'ın Malloc ve Scribble korumalarını da ekleyin. Derleyici uyarıları tanısal olduğu ve zaman içinde daha iyi oldukları için mümkün olduğu kadar çok standart kullanarak mümkün olduğu kadar çok derleyici kullanmalısınız. Gümüş mermi yoktur ve tek beden herkese uymaz. Ne kadar çok araç ve derleyici kullanırsanız, kapsama alanı o kadar fazla olur, çünkü her bir takımın güçlü ve zayıf yönleri vardır.