2010-12-06 14 views
6

Büyük bir monolitik uygulama özel bir yapı oluşturmaya çalışıyorum. Çözmeyi denediğim sorun, büyük bellek ayırmalarını çoğaltmak (30-80 gigabayt, işletim sistemi tarafından karar vererek) çoğaltmaktır. Sorunun bir negatif 32 bitlik tamsayı değerine yeniden boyutlandırılan bir std :: vektörü olduğunu düşünüyorum. Bu davranışı sergileyen tek platform Solaris'tir (belki de bu tür bitişik bellek parçalarını başarılı bir şekilde tahsis etmeyi başaran tek platformdur). Genel olarak std :: vektörünü sınıfımla değiştirebilir, tüm çağrıları gerçek vektöre aktarabilir, şüpheli ayırmaları izleyebilir miyim (size > 0x7FFFFFFFu)? Seçmeli olarak size_t ve resize() yöntemlerini kullanan kurucuyu değiştirebilir misiniz? Belki de küresel operatörü yeni kandırıyor mu?Devasa bellek ayırmalarını izlemek için global operatörü yeniliyor mu?

+1

32 bit değeri IMO'nun 30-80 GigaByte ile sonuçlanamaz, yani 64 bit –

+0

anlamına gelir Bir 0xFFFFFFFF 8 baytlık yapılar dizisi ~ 34 gigabayt alır. –

+0

Düzeltilmeye hazırlanıyorum –

cevap

5

Neden böyle bir şey yapmıyorsunuz? hemen sorunu bulur if bir kesme noktası ayarlama

void *operator new(size_t size) 
{ 
    // if (size > MAX_SIZE) ... 
    return malloc(size); 
} 

void *operator new [](size_t size) 
{ 
    // if (size > MAX_SIZE) ... 
    return malloc(size); 
} 

.

+0

Evet, başarmak istediğim buydu. Elbette, 'yeni operatör' platformun standart kütüphanesinde zaten tanımlanmıştır, bu yüzden sadece ikinci bir uygulama sağlayamam. –

+1

Evet yapabilirsin. Denedin mi? Bağlantı hataları alıyor musunuz? – detunized

+0

Eğer böyle yapabilsem harika olur. Deneyeceğim. –

2

Yaptığınız anda vektörünüzde özel bir ayırıcı sağlayabilirsiniz.

std::allocator'a yetki verebilirsiniz ve istenen bellek boyutunu ilk olarak güvenlik duvarı ile güvenlik altına alabilirsiniz.

+0

Bakın, sorun şu ki, kodun hangi bölümünün yanlış olduğunu bilmiyorum. Tüm kod tabanı (üçüncü taraf kütüphaneleri dahil), bir vektörün kullanıldığı her yerde özel ayırıcılar ile değiştirmek mümkün değildir. –

+0

Evet, o zaman bu daha zor. Q, zaten hangi vektörün olduğunu bildiğiniz gibi okuyun. Platformunuz, calltack oluşturarak yığın bloklarını ilişkilendirmek için herhangi bir araç sunuyor mu? –

+0

Şüpheli bir durum tespit ettiğimde çağrı yığınını kaydedebilirim. Soru, bir vektörü kullanarak her bir sınıfı değiştirmeden, küresel olarak nasıl algılayacağıdır. –

0

Sorunlu platformda std::vector sınıfının uygulanmasına göz atın. Her bir uygulama, bellek yönetimini farklı şekilde işler (örneğin, vektörün şu andaki tahsisat boyutu dışında bir nesne eklediğinizde, şu anda ayrılmış alanın iki katı). Nesneleriniz yeterince büyükse ve/veya vektöre çok sayıda giriş eklendiyse, bilgisayardaki mevcut (bitişik) belleğin ötesine geçmeye çalışmak mümkün olabilir. Bu durumda, bu vektör için özel bir ayırıcıya bakmak isteyeceksiniz.

Bir vektörde çok fazla büyük öğe saklıyorsanız, başka bir koleksiyona (örneğin, std::list) bakmak veya gerçek nesneler yerine işaretçileri depolamayı deneyebilirsiniz.

+0

Çözmeyi denediğim sorun, daha az bellek kullanmak için kodun nasıl değiştirileceği değil.Vector.resize ((size_t) (- 1)) 'işlevini etkin bir şekilde yürüten kod parçasını bulmaya çalışıyorum. Bu parça belirlendikten sonra, düzeltmek için önemsiz bir görev olmalıdır. –

+0

Koşullu kesme noktası yeteneğine sahip bir hata ayıklayıcıya erişiminiz varsa, bu hile yapar. Aksi halde, koleksiyonunuzu ikiye bölmeyi deneyin ve aynı sorunla karşılaşıp karşılaşmadığınızı test edin. Sorunu görene kadar koleksiyonunuzu kalan öğelerin yarısına kadar artırın. Bağırsak reaksiyonum, stok tahsisatçısının, mevcut kapasitesini iki katına çıkararak koleksiyonunuzun kapasitesini artırarak ve tahsis etmek için bitişik belleğin tükenmesiyle birlikte bir yere yerleştirilebilecektir. –

+0

kod, QA ortamında müşterinin sitesinde çalıştırılacaktır. Bu çalışmanın sonuçlarına erişebilirim (log dosyaları), ancak bir hata ayıklayıcısında çalıştırmasını talep edemem. –

0

Atanmayı izlemek için kendi allocator türünü std::vector türüne sağlayabilirsiniz. Ama bunun sebebi şüpheliyim. İlk olarak, (30-80GB) boyutlarına bakarak, bunun 64 bitlik bir kod olduğu sonucuna varıyorum. 32-bit negatif tamsayı değeri, 64-bit olan vektör büyüklüğüne nasıl değer kazandırabilirdi, değeri korumak için önce 64-bit'e yükseltilmiş olurdu? İkincisi, eğer bu problem sadece Solaris'te gerçekleşirse, o zaman farklı bir problemi gösterebilir. Hatırladığım kadarıyla, Solaris, tahsis üzerine belleği işleyen tek işletim sistemidir, diğer işletim sistemleri, yalnızca bu bellek sayfaları gerçekte kullanılıncaya kadar tahsis edilen adres alanını işaretler. Bu yüzden kullanılmayan tahsisleri arardım.

+0

Negatif 32 bitlik değer, vektör boyutuna nasıl dönüştürebilir? Bunun gibi bir şey: 'uint32_t count = (uint32_t) GetNumberOfThings(); std :: vektör şeyler (Thing(), count); 'GetNumberOfThings 'hatada -1 döndürdüğünde. Ve evet, mevcut kod tabanı çok fazla 32 bit büyüklükte değişken kullanır ve hatta 32 bit boyutunda özel bir vektör uygulaması vardır. Sorun, sorunlu kod parçalarını takip ediyor ... –

İlgili konular