How can Civ4 crashdumps help find bugs?

If you aren't already familiar with using debuggers, your best bet is to put a lot of print statements in your changed code, so you can see at what point it is crashing.
 
Looks like debugging isn't for me.
I also don't know how to use print statements. ;) Isn't that something for python?
 
Looks like debugging isn't for me.
I also don't know how to use print statements. ;) Isn't that something for python?
Print statements are useful for debugging any language. :p The SDK has built-in procedures for logging messages to a file. Here is an example that I have used to log messages to the file "sdk.log" when debugging the CvPlayerAI::AI_civicTrade() function.
Code:
	CvString szLogMsg;
	szLogMsg.Format("Inside CvPlayerAI::AI_civicTrade( eCivic = %d (%ls), ePlayer = %d (%ls) ).", (int)eCivic, GC.getCivicInfo(eCivic).getText(), (int)ePlayer, GET_PLAYER(ePlayer).getName());
	gDLL->logMsg("sdk.log", szLogMsg);
	szLogMsg.Format("The player evaluating the deal is %d (%ls).", getID(), getName());
	gDLL->logMsg("sdk.log", szLogMsg);
You can use whatever filename you want; it will appear in the Logs directory of your My Games folder along with all the normal civ4 log files. Here's sample output:
Code:
[126033.953] Inside CvPlayerAI::AI_civicTrade( eCivic = 21 (Organized Religion), ePlayer = 0 (Daveleiman) ).
[126033.953] The player evaluating the deal is 4 (Elizabeth).
...
[126088.570] Inside CvPlayerAI::AI_civicTrade( eCivic = 4 (Universal Suffrage), ePlayer = 0 (Daveleiman) ).
[126088.570] The player evaluating the deal is 8 (Hannibal).


It is also sometimes useful to output messages in-game which you can do via gDLL->getInterfaceIFace()->addMessage(). Here's an example from original game code ( CvCity::setWeLoveTheKingDay() )which shows the "We love the King day" message:
Code:
			szBuffer = gDLL->getText("TXT_KEY_CITY_CELEBRATE", getNameKey(), GC.getCivicInfo(eCivic).getWeLoveTheKing());
			gDLL->getInterfaceIFace()->addMessage(getOwnerINLINE(), false, GC.getEVENT_MESSAGE_TIME(), szBuffer, "AS2D_WELOVEKING", MESSAGE_TYPE_MINOR_EVENT, ARTFILEMGR.getInterfaceArtInfo("INTERFACE_HAPPY_PERSON")->getPath(), (ColorTypes)GC.getInfoTypeForString("COLOR_WHITE"), getX_INLINE(), getY_INLINE(), true, true);
 
Thanks. Is setting LoggingEnabled to one the only thing needed to get logging started? Or is what you're saying something different?
What's MessageLog and the other logs?

; Enable the logging system
LoggingEnabled = 0

; Enable synchronization logging
SynchLog = 0

; Overwrite old network and message logs
OverwriteLogs = 1

; Enable rand event logging
RandLog = 0

; Enable message logging
MessageLog = 0

Edit: I don't see any szLogMsg present in unmodded SDK code.
But just adding the code, somewhat modified, you posted at the beginning(?) of a function is enough for it to work??
 
LoggingEnabled should probably be enough to do it; I've got all of them turned on for the simple reason that I'm not sure exactly what they all do and it doesn't seem to hurt. :p

Yeah, using a modified version of that code should be enough. Doesn't necessarily need to be at the beginning of the function though. The first statement in my example:
Code:
CvString szLogMsg;
declares szLogMsg as a string variable. Using szLogMsg.Format() afterwards is basically like doing a printf with the results stored in szLogMsg. Then gDLL->logMsg("sdk.log", szLogMsg) says to output the contents of szLogMsg to the file "sdk.log".

There are some other optional arguments which can be passed to logMsg too. The full declaration can be seen in CvDLLUtilityIfaceBase.h:
Code:
virtual void logMsg(const TCHAR* pLogFileName, const TCHAR* pBuf, bool bWriteToConsole=false, bool bTimeStamp=true) = 0;
 
Top Bottom