MFC Hata Ayıklama Teknikleri
Bir MFC programında hata ayıklarsanız, bu hata ayıklama teknikleri yararlı olabilir.
Bu konuda,
MFC'de bellek sızıntılarını algılama
AfxDebugBreak
MFC, kaynak kodda kesme noktalarını sabit kodlamak için özel bir AfxDebugBreak işlevi sağlar:
AfxDebugBreak( );
Intel platformlarında, AfxDebugBreak
çekirdek kodu yerine kaynak kodda sonlanan aşağıdaki kodu üretir:
_asm int 3
Diğer platformlarda yalnızca AfxDebugBreak
öğesini çağırır DebugBreak
.
Yayın derlemesi oluştururken veya bunları çevrelemek için kullanırken #ifdef _DEBUG
deyimleri kaldırdığınızdan AfxDebugBreak
emin olun.
TRACE makro
Hata ayıklayıcısı Çıktı penceresinde programınızdan gelen iletileri görüntülemek için ATLTRACE makrosundan veya MFC TRACE makrosundan yararlanabilirsiniz. Onaylar gibi izleme makroları da yalnızca programınızın Hata Ayıklama sürümünde etkindir ve Yayın sürümünde derlendiğinde kaybolur.
Aşağıdaki örneklerde TRACE makrosunu kullanmanın bazı yolları gösterilmektedir. gibi printf
, TRACE makro da bir dizi bağımsız değişkeni işleyebilir.
int x = 1;
int y = 16;
float z = 32.0;
TRACE( "This is a TRACE statement\n" );
TRACE( "The value of x is %d\n", x );
TRACE( "x = %d and y = %d\n", x, y );
TRACE( "x = %d and y = %x and z = %f\n", x, y, z );
TRACE makro, hem char* hem de wchar_t* parametrelerini uygun şekilde işler. Aşağıdaki örneklerde TRACE makrosunun farklı dize parametresi türleriyle birlikte kullanılması gösterilmektedir.
TRACE( "This is a test of the TRACE macro that uses an ANSI string: %s %d\n", "The number is:", 2);
TRACE( L"This is a test of the TRACE macro that uses a UNICODE string: %s %d\n", L"The number is:", 2);
TRACE( _T("This is a test of the TRACE macro that uses a TCHAR string: %s %d\n"), _T("The number is:"), 2);
TRACE makro hakkında daha fazla bilgi için bkz. Tanılama Hizmetleri.
MFC'de bellek sızıntılarını algılama
MFC, ayrılan ancak hiçbir zaman serbest bırakılmamış belleği algılamaya yönelik sınıflar ve işlevler sağlar.
Bellek ayırmalarını izleme
MFC'de, bellek sızıntılarını bulmaya yardımcı olmak için yeni işlecin yerine makro DEBUG_NEW kullanabilirsiniz. Programınızın Hata ayıklama sürümünde, DEBUG_NEW
ayırmış olduğu her nesne için dosya adını ve satır numarasını izler. Programınızın Yayın sürümünü derlediğinizde, DEBUG_NEW
dosya adı ve satır numarası bilgileri olmadan basit bir yeni işleme çözümler. Bu nedenle, programınızın Yayın sürümünde hız cezası ödemezsiniz.
Yeni yerine kullanmak DEBUG_NEW
üzere programınızın tamamını yeniden yazmak istemiyorsanız, bu makroları kaynak dosyalarınızda tanımlayabilirsiniz:
#define new DEBUG_NEW
Bir nesne dökümü yaptığınızda, ile DEBUG_NEW
ayrılan her nesne, ayrılan dosya ve satır numarasını göstererek bellek sızıntılarının kaynaklarını saptamanıza olanak sağlar.
MFC çerçevesinin Hata Ayıklama sürümü otomatik olarak kullanır DEBUG_NEW
, ancak kodunuz kullanmaz. avantajlarından yararlanmak DEBUG_NEW
istiyorsanız, yukarıda gösterildiği gibi açıkça veya yeni #define kullanmanız DEBUG_NEW
gerekir.
Bellek tanılamasını etkinleştirme
Bellek tanılama özelliklerini kullanabilmeniz için önce tanılama izlemeyi etkinleştirmeniz gerekir.
Bellek tanılamasını etkinleştirmek veya devre dışı bırakmak için
Tanılama bellek ayırıcısını etkinleştirmek veya devre dışı bırakmak için genel afxEnableMemoryTracking işlevini çağırın. Hata ayıklama kitaplığında bellek tanılamaları varsayılan olarak açık olduğundan, bu işlevi genellikle program yürütme hızını artıran ve tanılama çıkışını azaltan geçici olarak kapatmak için kullanırsınız.
afxMemDF ile belirli bellek tanılama özelliklerini seçmek için
Bellek tanılama özellikleri üzerinde daha hassas bir denetim istiyorsanız, MFC genel değişkeni afxMemDF değerini ayarlayarak tek tek bellek tanılama özelliklerini seçmeli olarak açıp kapatabilirsiniz. Bu değişken, afxMemDF numaralandırılmış türü tarafından belirtilen aşağıdaki değerlere sahip olabilir.
Değer Açıklama allocMemDF Tanılama bellek ayırıcısını açın (varsayılan). delayFreeMemDF Çağırırken delete
veyafree
program çıkana kadar bellek boşaltmayı geciktirin. Bu, programınızın mümkün olan en fazla bellek miktarını ayırmasına neden olur.checkAlwaysMemDF Bellek her ayrıldığında veya serbest bırakıldıysa AfxCheckMemory'i çağır. Bu değerler, burada gösterildiği gibi bir mantıksal VEYA işlemi gerçekleştirilerek birlikte kullanılabilir:
afxMemDF = allocMemDF | delayFreeMemDF | checkAlwaysMemDF;
Bellek anlık görüntüleri alma
CMemoryState nesnesi oluşturun ve CMemoryState::Checkpoint üye işlevini çağırın. Bu, ilk bellek anlık görüntüsünü oluşturur.
Programınız bellek ayırma ve serbest bırakma işlemlerini gerçekleştirdikten sonra başka bir
CMemoryState
nesne oluşturun ve bu nesne için çağrısıCheckpoint
yapın. Bu, bellek kullanımının ikinci bir anlık görüntüsünü alır.Üçüncü
CMemoryState
bir nesne oluşturun ve CMemoryState::D ifference üye işlevini çağırın ve öncekiCMemoryState
iki nesne için bağımsız değişken olarak sağlayın. İki bellek durumu arasında bir fark varsa işlevDifference
sıfır olmayan bir değer döndürür. Bu, bazı bellek bloklarının serbest bırakılmadığını gösterir.Bu örnekte kodun nasıl göründüğü gösterilir:
// Declare the variables needed #ifdef _DEBUG CMemoryState oldMemState, newMemState, diffMemState; oldMemState.Checkpoint(); #endif // Do your memory allocations and deallocations. CString s("This is a frame variable"); // The next object is a heap object. CPerson* p = new CPerson( "Smith", "Alan", "581-0215" ); #ifdef _DEBUG newMemState.Checkpoint(); if( diffMemState.Difference( oldMemState, newMemState ) ) { TRACE( "Memory leaked!\n" ); } #endif
Bellek denetimi deyimlerinin #ifdef _DEBUG / #endif bloklar tarafından köşeli ayraç içine alındığını ve böylece bunların yalnızca programınızın Hata ayıklama sürümlerinde derlendiğine dikkat edin.
Artık bir bellek sızıntısı olduğunu bildiğinize göre, bulmanıza yardımcı olacak CMemoryState::D umpStatistics adlı başka bir üye işlevini kullanabilirsiniz.
Bellek istatistiklerini görüntüleme
CMemoryState::D ifference işlevi iki bellek durumu nesnesine bakar ve yığından başlangıç ve bitiş durumları arasında serbest bırakılmayan nesneleri algılar. Bellek anlık görüntülerini alıp kullanarak CMemoryState::Difference
karşılaştırdıktan sonra serbest bırakılmamış nesneler hakkında bilgi almak için CMemoryState::D umpStatistics çağırabilirsiniz.
Aşağıdaki örneği inceleyin:
if( diffMemState.Difference( oldMemState, newMemState ) )
{
TRACE( "Memory leaked!\n" );
diffMemState.DumpStatistics();
}
Örnekteki örnek döküm aşağıdaki gibi görünür:
0 bytes in 0 Free Blocks
22 bytes in 1 Object Blocks
45 bytes in 4 Non-Object Blocks
Largest number used: 67 bytes
Total allocations: 67 bytes
Serbest bloklar, olarak ayarlandıysa afxMemDF
delayFreeMemDF
serbest bırakma işlemi geciken bloklardır.
İkinci satırda gösterilen sıradan nesne blokları yığında ayrılmış olarak kalır.
Nesne olmayan bloklar ile new
ayrılan dizileri ve yapıları içerir. Bu durumda, yığında nesne olmayan dört blok ayrılmış ancak serbest bırakılmamış.
Largest number used
program tarafından herhangi bir zamanda kullanılan en yüksek belleği verir.
Total allocations
program tarafından kullanılan toplam bellek miktarını verir.
Nesne dökümlerini alma
MFC programında CMemoryState::D umpAllObjectsSince kullanarak serbest bırakılmamış yığındaki tüm nesnelerin açıklamasını döküm edebilirsiniz. DumpAllObjectsSince
son CMemoryState::Checkpoint'ten sonra ayrılan tüm nesneleri döküm eder. Hiçbir Checkpoint
çağrı yapılmadıysa, DumpAllObjectsSince
şu anda bellekte olan tüm nesneleri ve nesne dışı nesneleri döküm eder.
Dekont
MFC nesne dökümünü kullanabilmeniz için önce tanılama izlemeyi etkinleştirmeniz gerekir.
Dekont
MFC, programınız çıktığında sızdırılan tüm nesnelerin dökümünü otomatik olarak alır, bu nedenle bu noktada nesnelerin dökümünü almak için kod oluşturmanız gerekmez.
Aşağıdaki kod, iki bellek durumu karşılaştırarak bellek sızıntısını test eder ve bir sızıntı algılanırsa tüm nesnelerin dökümünü alır.
if( diffMemState.Difference( oldMemState, newMemState ) )
{
TRACE( "Memory leaked!\n" );
diffMemState.DumpAllObjectsSince();
}
Döküm içeriği şöyle görünür:
Dumping objects ->
{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4
Last Name: Smith
First Name: Alan
Phone #: 581-0215
{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long
Çoğu satırın başındaki küme ayraçlarındaki sayılar, nesnelerin ayrılma sırasını belirtir. En son ayrılan nesne en yüksek sayıya sahiptir ve dökümünün en üstünde görünür.
Bir nesne dökümünün en fazla bilgi miktarını elde etmek için türetilmiş herhangi bir CObject
nesnenin Dump
üye işlevini geçersiz kılarak nesne dökümünü özelleştirebilirsiniz.
Genel değişkeni _afxBreakAlloc
küme ayraçlarında gösterilen sayıya ayarlayarak belirli bir bellek ayırmada kesme noktası ayarlayabilirsiniz. Programı yeniden çalıştırırsanız, ayırma gerçekleştiğinde hata ayıklayıcı yürütmeyi bozar. Ardından, programınızın bu noktaya nasıl geldiğini görmek için çağrı yığınına bakabilirsiniz.
C çalışma zamanı kitaplığı, C çalışma zamanı ayırmaları için kullanabileceğiniz benzer bir işleve _CrtSetBreakAlloc sahiptir.
Bellek dökümlerini yorumlama
Bu nesne dökümünü daha ayrıntılı olarak inceleyin:
{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4
Last Name: Smith
First Name: Alan
Phone #: 581-0215
{1} strcore.cpp(80) : non-object block at $00A7516E, 25 bytes long
Bu dökümü oluşturan programın biri yığında, diğeri yığında olmak üzere yalnızca iki açık ayırması vardı:
// Do your memory allocations and deallocations.
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
Oluşturucu, CPerson
üye değişkenlerini başlatmak CString
için char
kullanılan işaretçi olan üç bağımsız değişken alır. Bellek dökümü içinde nesneyi üç nesne olmayan blokla (3, 4 ve 5) birlikte görebilirsiniz CPerson
. Bunlar üye değişkenlerin CString
karakterlerini tutar ve nesne yıkıcı çağrıldığında CPerson
silinmez.
2 numaralı blok nesnenin CPerson
kendisidir. $51A4
bloğun adresini temsil eder ve ardından DumpAllObjectsSince tarafından çağrıldığında ::Dump
tarafından çıktısı CPerson
alınan nesnenin içeriği izler.
1 numaralı bloğun, kare değişkenindeki CString
karakter sayısıyla eşleşen sıra numarası ve boyutu nedeniyle çerçeve CString
değişkeniyle ilişkilendirildiğini tahmin edebilirsiniz. Çerçevede ayrılan değişkenler, çerçeve kapsamın dışına çıktığında otomatik olarak serbest bırakılır.
Çerçeve Değişkenleri
Genel olarak, çerçeve değişkenleri kapsam dışına çıktığında otomatik olarak serbest bırakıldıklarından, çerçeve değişkenleriyle ilişkili yığın nesneleri konusunda endişelenmemelisiniz. Bellek tanılama dökümlerinizde dağınıklığı önlemek için Checkpoint
çağrılarınızı çerçeve değişkenleri kapsamı dışında olacak şekilde konumlandırmanız gerekir. Örneğin, burada gösterildiği gibi kapsam köşeli ayraçlarını önceki ayırma kodunun çevresine yerleştirin:
oldMemState.Checkpoint();
{
// Do your memory allocations and deallocations ...
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
}
newMemState.Checkpoint();
Kapsam köşeli ayraçları yerleştirildiğinde, bu örneğin bellek dökümü aşağıdaki gibidir:
Dumping objects ->
{5} strcore.cpp(80) : non-object block at $00A7521A, 9 bytes long
{4} strcore.cpp(80) : non-object block at $00A751F8, 5 bytes long
{3} strcore.cpp(80) : non-object block at $00A751D6, 6 bytes long
{2} a CPerson at $51A4
Last Name: Smith
First Name: Alan
Phone #: 581-0215
Nesne Olmayan Ayırmalar
Bazı ayırmaların nesneler (örneğin CPerson
) ve bazılarının nesne olmayan ayırmalar olduğuna dikkat edin. "Nesne dışı ayırmalar", int
, veya long
gibi char
ilkel C türlerinden CObject
türetilmemiş nesneler veya ayırmaları için ayırmalardır. CObject türetilmiş sınıfı iç arabellekler gibi ek alan ayırırsa, bu nesneler hem nesne hem de nesne olmayan ayırmaları gösterir.
Bellek Sızıntılarını Önleme
Yukarıdaki kodda çerçeve değişkeniyle ilişkili bellek bloğunun CString
otomatik olarak serbest bırakıldığına ve bellek sızıntısı olarak gösterilmediğine dikkat edin. Kapsam belirleme kurallarıyla ilişkili otomatik serbest bırakma işlemi, çerçeve değişkenleriyle ilişkili bellek sızıntılarının çoğunu üstlenir.
Ancak yığında ayrılan nesneler için, bellek sızıntısını önlemek için nesneyi açıkça silmeniz gerekir. Önceki örnekteki son bellek sızıntısını temizlemek için yığında ayrılan nesneyi aşağıdaki gibi silin CPerson
:
{
// Do your memory allocations and deallocations.
CString s("This is a frame variable");
// The next object is a heap object.
CPerson* p = new CPerson( "Smith", "Alan", "581-0215" );
delete p;
}
Nesne dökümlerini özelleştirme
CObject'ten bir sınıf türetdiğinizde, Nesneleri Çıkış penceresine döküm etmek için DumpAllObjectsSince kullandığınızda ek bilgi sağlamak için üye işlevini geçersiz kılabilirsinizDump
.
İşlev, Dump
nesnenin üye değişkenlerinin metinsel bir gösterimini döküm bağlamına (CDumpContext) yazar. Döküm bağlamı G/Ç akışına benzer. bir öğesine veri CDumpContext
göndermek için ekleme işlecini (<<) kullanabilirsiniz.
İşlevi Dump
geçersiz kıldığınızda, önce temel sınıf nesnesinin içeriğini döküm etmek için temel sınıf sürümünü Dump
çağırmanız gerekir. Ardından türetilmiş sınıfınızın her üye değişkeni için metinsel bir açıklama ve değer çıktısı alır.
işlevinin Dump
bildirimi şöyle görünür:
class CPerson : public CObject
{
public:
#ifdef _DEBUG
virtual void Dump( CDumpContext& dc ) const;
#endif
CString m_firstName;
CString m_lastName;
// And so on...
};
Nesne dökümü yalnızca programınızda hata ayıklarken anlamlı olduğundan, işlevin Dump
bildirimi bir #ifdef _DEBUG / #endif bloğuyla köşeli ayraç içine alınır.
Aşağıdaki örnekte, Dump
işlevi ilk olarak temel sınıfı için işlevini çağırır Dump
. Ardından, tanılama akışına üyenin değeriyle birlikte her üye değişkeninin kısa bir açıklamasını yazar.
#ifdef _DEBUG
void CPerson::Dump( CDumpContext& dc ) const
{
// Call the base class function first.
CObject::Dump( dc );
// Now do the stuff for our specific class.
dc << "last name: " << m_lastName << "\n"
<< "first name: " << m_firstName << "\n";
}
#endif
Döküm çıkışının nereye gideceğini belirtmek için bir CDumpContext
bağımsız değişken sağlamanız gerekir. MFC'nin Hata Ayıklama sürümü, çıktıyı hata ayıklayıcıya gönderen adlı afxDump
önceden tanımlanmış CDumpContext
bir nesne sağlar.
CPerson* pMyPerson = new CPerson;
// Set some fields of the CPerson object.
//...
// Now dump the contents.
#ifdef _DEBUG
pMyPerson->Dump( afxDump );
#endif
MFC Hata Ayıklama derlemesinin boyutunu küçültme
Büyük bir MFC uygulamasının hata ayıklama bilgileri çok fazla disk alanı kaplayabilir. Boyutu küçültmek için şu yordamlardan birini kullanabilirsiniz:
/Z7 yerine /Z7, /Zi, /ZI (Hata Ayıklama Bilgileri Biçimi) seçeneğini kullanarak MFC kitaplıklarını yeniden oluşturun. Bu seçenekler, kitaplığın tamamı için hata ayıklama bilgilerini içeren tek bir program veritabanı (PDB) dosyası oluşturarak yedekliliği azaltır ve alan tasarrufu sağlar.
Hata ayıklama bilgileri olmadan MFC kitaplıklarını yeniden oluşturun (/Z7, /Zi, /ZI (Hata Ayıklama Bilgileri Biçimi) seçeneği yok). Bu durumda, hata ayıklama bilgilerinin olmaması MFC kitaplık kodu içinde hata ayıklayıcı olanaklarının çoğunu kullanmanızı engeller, ancak MFC kitaplıkları zaten ayrıntılı bir şekilde hata ayıklandığından, bu sorun olmayabilir.
Yalnızca aşağıda açıklandığı gibi seçilen modüller için hata ayıklama bilgileriyle kendi uygulamanızı oluşturun.
Seçili modüller için hata ayıklama bilgileriyle MFC uygulaması oluşturma
MFC hata ayıklama kitaplıklarıyla seçilen modülleri oluşturmak, bu modüllerdeki adımlama ve diğer hata ayıklama olanaklarını kullanmanıza olanak tanır. Bu yordam, projenin hem Hata Ayıklama hem de Yayın yapılandırmalarını kullanır, bu nedenle aşağıdaki adımlarda açıklanan değişiklikleri zorunlu kılar (ve ayrıca tam sürüm derlemesi gerektiğinde "tümünü yeniden derleme" gerekir).
Çözüm Gezgini'da projeyi seçin.
Görünüm menüsünde Özellik Sayfaları'nı seçin.
İlk olarak yeni bir proje yapılandırması oluşturacaksınız.
<Proje> Özellik Sayfaları iletişim kutusunda Configuration Manager düğmesine tıklayın.
Configuration Manager iletişim kutusunda projenizi kılavuzda bulun. Yapılandırma sütununda Yeni...> öğesini seçin<.
Yeni Proje Yapılandırması iletişim kutusunda, Proje Yapılandırma Adı kutusuna yeni yapılandırmanız için "Kısmi Hata Ayıklama" gibi bir ad yazın.
Ayarlar kopyala listesinde Yayın'ı seçin.
Tamam'a tıklayarak Yeni Proje Yapılandırması iletişim kutusunu kapatın.
Configuration Manager iletişim kutusunu kapatın.
Şimdi tüm proje için seçenekleri ayarlayacaksınız.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Özellikleri klasörünün altında Genel kategorisini seçin.
Proje ayarları kılavuzunda Proje Varsayılanları'nı (gerekirse) genişletin.
Proje Varsayılanları'nın altında MFC Kullanımı'yı bulun. Geçerli ayar kılavuzun sağ sütununda görünür. Geçerli ayara tıklayın ve Bunu Statik Kitaplıkta MFC Kullan olarak değiştirin.
Özellikler Sayfaları iletişim kutusunun sol bölmesinde C/C++ klasörünü açın ve Önişlemci'yi seçin. Özellikler kılavuzunda Önişlemci Tanımları'nı bulun ve "NDEBUG" yerine "_DEBUG" yazın.
Özellikler Sayfaları iletişim kutusunun sol bölmesinde Bağlayıcı klasörünü açın ve Giriş Kategorisi'ni seçin. Özellikler kılavuzunda Ek Bağımlılıklar'ı bulun. Ek Bağımlılıklar ayarına "NAFXCWD yazın. LIB" ve "LIBCMT."
Yeni derleme seçeneklerini kaydetmek için Tamam'a tıklayın ve Özellik Sayfaları iletişim kutusunu kapatın.
Oluştur menüsünden Yeniden Oluştur'a tıklayın. Bu, modüllerinizdeki tüm hata ayıklama bilgilerini kaldırır, ancak MFC kitaplığını etkilemez.
Şimdi hata ayıklama bilgilerini uygulamanızda seçili modüllere geri eklemeniz gerekir. Kesme noktaları ayarlayabileceğinizi ve diğer hata ayıklayıcı işlevlerini yalnızca hata ayıklama bilgileriyle derlediğiniz modüllerde gerçekleştirebileceğinizi unutmayın. Hata ayıklama bilgilerini eklemek istediğiniz her proje dosyası için aşağıdaki adımları uygulayın:
Çözüm Gezgini'da projenizin altında bulunan Kaynak Dosyalar klasörünü açın.
Hata ayıklama bilgilerini ayarlamak istediğiniz dosyayı seçin.
Görünüm menüsünde Özellik Sayfaları'nı seçin.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Ayarlar klasörünün altında C/C++ klasörünü açın ve Genel kategorisini seçin.
Özellikler kılavuzunda Hata Ayıklama Bilgileri Biçimi'ni bulun .
Hata Ayıklama Bilgileri Biçimi ayarlarına tıklayın ve hata ayıklama bilgileri için istenen seçeneği (genellikle /ZI) seçin.
Uygulama sihirbazı tarafından oluşturulan bir uygulama kullanıyorsanız veya önceden derlenmiş üst bilgileriniz varsa, diğer modülleri derlemeden önce önceden derlenmiş üst bilgileri kapatmanız veya yeniden derlemeniz gerekir. Aksi takdirde, C4650 uyarı ve C2855 hata iletisi alırsınız. Proje> Özellikleri iletişim kutusundaki (Yapılandırma Özellikleri klasörü, C/C++ alt klasörü, Önceden Derlenmiş Üst Bilgiler kategorisi) Önceden Derlenmiş Üst Bilgileri Oluştur/Kullan ayarını< değiştirerek önceden derlenmiş üst bilgileri kapatabilirsiniz.
Derleme menüsünden Derle'yi seçerek güncel olmayan proje dosyalarını yeniden oluşturun.
Bu konuda açıklanan tekniğin alternatifi olarak, her dosya için tek tek seçenekleri tanımlamak için bir dış derleme dosyası kullanabilirsiniz. Bu durumda, MFC hata ayıklama kitaplıklarına bağlanmak için her modül için _DEBUG bayrağı tanımlamanız gerekir. MFC yayın kitaplıklarını kullanmak istiyorsanız NDEBUG tanımlamanız gerekir. Dış derleme dosyaları yazma hakkında daha fazla bilgi için bkz . NMAKE Başvurusu.