Allocating Zero or Less Memory in CvXMLLoadUtility...

Oops, wasn't paying close enough of attention, I had just done a search for BuildingInfo and copied the first line it gave me!


In your post you called the new function "NonCopyDefaultsReadPass2" which is not the proper name. So potentially that is your issue. You posted a CNDrp2 earlier though, and it was correct in there. Did you declare it in your CvInfos.h? Not sure if a virtual will yell at you for doing that wrong or not.

I probably just remembered the name slightly wrong, while typing on the forums. It isn't exactly a name that sticks with you...

Here's my CvInfos.h but I doubt it's wrong...
Code:
    bool readPass2(CvXMLLoadUtility* pXML);
    void copyNonDefaultsReadPass2(CvBuildingInfo* pClassInfo = NULL);
I really have problems seeing bold on the forum for some reason. Was the error line:

aInfos[iIndex]->copyNonDefaultsReadPass2(pClassInfo);

Well actually, the line right below it... Bolding with code doesn't show very well here, it's not just you.
 
Yeah, header looks fine, not easily messed up, so was a shot in the dark for a simple fix. But was thinking for the wrong line anyway.

SAFE_DELETE(pClassInfo);

If this line is the error, that means that pClassInfo = NULL at that point. That's a bigger issue, and should have caused problems during your CopyNonDef, but maybe we can get away with just dodging around it. Encase that line in an "if pClassInfo != NULL" check and see if it helps
 
Yeah, header looks fine, not easily messed up, so was a shot in the dark for a simple fix. But was thinking for the wrong line anyway.

SAFE_DELETE(pClassInfo);

If this line is the error, that means that pClassInfo = NULL at that point. That's a bigger issue, and should have caused problems during your CopyNonDef, but maybe we can get away with just dodging around it. Encase that line in an "if pClassInfo != NULL" check and see if it helps

Strange.


  • If I add the ReadPass2 code, but don't switch that true in the LoadGlobalInfoClass, the game loads, but my changes don't work.
  • If I don't add the ReadPass2 code, I get the error on the OP.
  • If I switch the true to false, with the Readpass2 code, I get that break and CTD while Init XML, on the end of the first page.
  • If I switch the true to false, with the readpass2 code, and add the "if pClassInfo != NULL" check, I get the error on the OP.

Hmm... What's left to do?
 
SAFE_DELETE() already checks the pointer for NULL and doesn't do anything if it is. That's the "safe" part of the name. There's no reason to check it for NULL yourself.

Are you sure you're supposed to delete it in the first place?
 
SAFE_DELETE() already checks the pointer for NULL and doesn't do anything if it is. That's the "safe" part of the name. There's no reason to check it for NULL yourself.

Are you sure you're supposed to delete it in the first place?

I'm fairly sure, since I didn't add that code, it's Firaxis code. That's just where it's breaking, according to my Debug DLL.
 
Okay, well if you guys can't help me, I'm ready to just say "screw it" and move the code to CivicInfos, despite that being slightly odd...
 
Wait... Readpass2 is for an array or string referencing the file ITSELF (Civic reference to a civic). I need to get in the habit of reading back a couple dozen posts on these threads so I remember the big picture.

READPASS2 IS USELESS HERE.

You need to create and utilize a readpass 3. Handling those with WoC is a bit more complicated, but for the base Firaxis portion it is considerably easier. Put the true back to false in XMLUtility, but you'll have to add a loop over buildingInfos AFTER the point where civics load. During ::read(pXML) you'll load all of the information into a list (aszExtraXMLForReadPass3 or whatever) and then parse it back out and delete it during pass3.
 
Wait... Readpass2 is for an array or string referencing the file ITSELF (Civic reference to a civic). I need to get in the habit of reading back a couple dozen posts on these threads so I remember the big picture.

READPASS2 IS USELESS HERE.

You need to create and utilize a readpass 3. Handling those with WoC is a bit more complicated, but for the base Firaxis portion it is considerably easier. Put the true back to false in XMLUtility, but you'll have to add a loop over buildingInfos AFTER the point where civics load. During ::read(pXML) you'll load all of the information into a list (aszExtraXMLForReadPass3 or whatever) and then parse it back out and delete it during pass3.

Good thing I read this post. I was just about to strip my changes out...

I'll see what I can come up with. How is the readpass3 handled with the CvXMLLoadUtilitySet?

Edit:

I'm not really sure what I'm doing in CvInfos, could you point me to something that I could use as an example?
 
All the readpass3's are for regular integers, I don't see any for booleans, much less boolean arrays. I don't know what to put for this section:

Code:
bool CvBuildingInfo::readPass3()
{
	if (m_aszExtraXMLforPass3.size() < 1)
	{
		FAssert(false);
		return false;
	}

	int iTextDefault = -1;
	int iSize = m_aszExtraXMLforPass3.size();	
	for ( int i = 0; i < iSize; i++ )
	{ 
		if ( GC.getInfoTypeForString(m_aszExtraXMLforPass3[iSize - ( i + 1)]) != iTextDefault)
		{
			m_pbPrereqOrCivics = GC.getInfoTypeForString(m_aszExtraXMLforPass3[iSize - ( i + 1)]);
			m_pbPrereqAndCivics = GC.getInfoTypeForString(m_aszExtraXMLforPass3[iSize - ( i + 1)]);
			break;
		}
	}		

	m_aszExtraXMLforPass3.clear();

	return true;
}

Because that doesn't compile because it was made for int's, not bool...
 
You have to look at Fall Further's code for worthwhile pass3 examples really. The pass3 stuff I saw in WoCLite was all backward from how I prefer to have it run, so be warned that it will look considerably different.

Tomorrow night while at work I can try to help you out better, but can't review code easily today :( Take a look at my code though and see how well you understand it. There should be quite a few examples, but be warned that you need to import a few functions from XMLLoadUtility as well.
 
Okay, I tried to mimic FF's ReadPass3 code to the best of my ability. I didn't add the CopyNonDefaults yet, as they are for WoC, and are not essential to getting the code to work. My SDK changes compiled, after several tries, but I had two warnings...

When I loaded the game up, I received a friendly CTD at Init.xml. Hopefully Xienwolf or EmperorFool can tell me what I did wrong.

Here's my ReadPass3:


Code:
bool CvBuildingInfo::readPass3()
{
	m_pbPrereqOrCivics = new bool[GC.getNumCivicInfos()];
    for (int iI = 0; iI < GC.getNumCivicInfos(); iI++)
	{
        m_pbPrereqOrCivics[iI] = false;
	}
    int iNumLoad = m_abPrereqOrCivicsforPass3.size();
	for(iI = 0; iI < iNumLoad; iI++)
	{
		FAssertMsg(GC.getInfoTypeForString(m_aszPrereqOrCivicsforPass3[iI]) >= 0, "Warning, about to leak memory in CvBuildingInfo::readPass3");
		[COLOR="Red"][B]m_pbPrereqOrCivics[GC.getInfoTypeForString(m_aszPrereqOrCivicsforPass3[iI])] += m_abPrereqOrCivicsforPass3[iI];[/B][/COLOR]
	}
    m_aszPrereqOrCivicsforPass3.clear();
    m_abPrereqOrCivicsforPass3.clear();
	
	m_pbPrereqAndCivics = new bool[GC.getNumCivicInfos()];
    for (int iI = 0; iI < GC.getNumCivicInfos(); iI++)
	{
        m_pbPrereqAndCivics[iI] = false;
	}
    int iNumLoad2 = m_abPrereqAndCivicsforPass3.size();
	for(iI = 0; iI < iNumLoad2; iI++)
	{
		FAssertMsg(GC.getInfoTypeForString(m_aszPrereqAndCivicsforPass3[iI]) >= 0, "Warning, about to leak memory in CvBuildingInfo::readPass3");
		[COLOR="Red"][B]m_pbPrereqAndCivics[GC.getInfoTypeForString(m_aszPrereqAndCivicsforPass3[iI])] += m_abPrereqAndCivicsforPass3[iI];[/B][/COLOR]
	}
    m_aszPrereqAndCivicsforPass3.clear();
    m_abPrereqAndCivicsforPass3.clear();
	
	return true;
}

This is also the section I get the two warnings. Bolded lines have the warnings. They are about unsafe mix of bool and int datatypes, but I am unsure what/how to change the code to fix it, since there are no ReadPass3 examples with boolean arrays to draw upon...

Also, here is the rest of my CvInfos.cpp code:
Spoiler :
Code:
CvBuildingInfo::CvBuildingInfo() :
...
m_pbPrereqOrCivics(NULL), //Afforess
m_pbPrereqAndCivics(NULL),
...

CvBuildingInfo::~CvBuildingInfo()
{...
	SAFE_DELETE_ARRAY(m_pbPrereqOrCivics); //Afforess
	SAFE_DELETE_ARRAY(m_pbPrereqAndCivics);
...
}

bool CvBuildingInfo::isPrereqOrCivics(int i) const
{
	FAssertMsg(i < GC.getNumCivicInfos(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_pbPrereqOrCivics ? m_pbPrereqOrCivics[i] : false;
}
...
bool CvBuildingInfo::isPrereqAndCivics(int i) const
{
	FAssertMsg(i < GC.getNumCivicInfos(), "Index out of bounds");
	FAssertMsg(i > -1, "Index out of bounds");
	return m_pbPrereqAndCivics ? m_pbPrereqAndCivics[i] : false;
}

int CvBuildingInfo::isPrereqOrCivicsVectorSize()					{return m_aszPrereqOrCivicsforPass3.size();}
CvString CvBuildingInfo::isPrereqOrCivicsNamesVectorElement(int i)	{return m_aszPrereqOrCivicsforPass3[i];}
int CvBuildingInfo::isPrereqOrCivicsValuesVectorElement(int i)		{return m_abPrereqOrCivicsforPass3[i];}
int CvBuildingInfo::isPrereqAndCivicsVectorSize()					{return m_aszPrereqAndCivicsforPass3.size();}
CvString CvBuildingInfo::isPrereqAndCivicsNamesVectorElement(int i)	{return m_aszPrereqAndCivicsforPass3[i];}
int CvBuildingInfo::isPrereqAndCivicsValuesVectorElement(int i)		{return m_abPrereqAndCivicsforPass3[i];}
...
void CvBuildingInfo::read(FDataStreamBase* stream)
{...

	SAFE_DELETE_ARRAY(m_pbPrereqOrCivics); //Afforess
	m_pbPrereqOrCivics = new bool[GC.getNumCivicInfos()];
	stream->Read(GC.getNumCivicInfos(), m_pbPrereqOrCivics);
	
	SAFE_DELETE_ARRAY(m_pbPrereqAndCivics);
	m_pbPrereqAndCivics = new bool[GC.getNumCivicInfos()];
	stream->Read(GC.getNumCivicInfos(), m_pbPrereqAndCivics);
...
}
void CvBuildingInfo::write(FDataStreamBase* stream)
{
...
	stream->Write(GC.getNumCivicInfos(), m_pbPrereqOrCivics); //Afforess
	stream->Write(GC.getNumCivicInfos(), m_pbPrereqAndCivics);
...
}

bool CvBuildingInfo::read(CvXMLLoadUtility* pXML)
{
...
	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"PrereqOrCivics"))
	{
		if (pXML->SkipToNextVal())
		{
			int iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
			int iTemp = 0;
			if (iNumSibs > 0)
			{
				if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
				{
					for (int i=0;i<iNumSibs;i++)
					{
						if (pXML->GetChildXmlVal(szTextVal))
						{
                            m_aszPrereqOrCivicsforPass3.push_back(szTextVal);
                            pXML->GetNextXmlVal(&iTemp);
                            m_abPrereqOrCivicsforPass3.push_back(iTemp);
							gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
						}

						if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
						{
							break;
						}
					}

					gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
				}
			}
		}

		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
	
	if (gDLL->getXMLIFace()->SetToChildByTagName(pXML->GetXML(),"PrereqAndCivics"))
	{
		if (pXML->SkipToNextVal())
		{
			int iNumSibs = gDLL->getXMLIFace()->GetNumChildren(pXML->GetXML());
			int iTemp = 0;
			if (iNumSibs > 0)
			{
				if (gDLL->getXMLIFace()->SetToChild(pXML->GetXML()))
				{
					for (int i=0;i<iNumSibs;i++)
					{
						if (pXML->GetChildXmlVal(szTextVal))
						{
                            m_aszPrereqAndCivicsforPass3.push_back(szTextVal);
                            pXML->GetNextXmlVal(&iTemp);
                            m_abPrereqAndCivicsforPass3.push_back(iTemp);
							gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
						}

						if (!gDLL->getXMLIFace()->NextSibling(pXML->GetXML()))
						{
							break;
						}
					}

					gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
				}
			}
		}

		gDLL->getXMLIFace()->SetToParent(pXML->GetXML());
	}
...
}
 
For booleans, you should not add, you should just set. Change "+=" to "=" in both places. Several people have commented they have trouble finding bold lines; I usually use red font instead of bold.
 
For booleans, you should not add, you should just set. Change "+=" to "=" in both places. Several people have commented they have trouble finding bold lines; I usually use red font instead of bold.

Okay. However, that doesn't resolve the CTD an init XML. Time to break out the Debug DLL, I suppose.
 
The value in your m_asz carry over was used to decide WHICH boolean to change. There are only 2 states for any boolean to be, so don't set them equal to anything other than "true" and you should be fine.

You shouldn't need m_abPrereqOrCivicsforPass3, since if the civic was listed at all, then you want to flag it.

Most of my arrays are written for XML looking like:
Code:
<BuildingCivics>
  <BuildingCivic>CIVIC_SOMETHING</BuildingCivic>
  <BuildingCivic>CIVIC_ANOTHER</BuildingCivic>
<BuildingCivics>

Rather than this:

Code:
<BuildingCivics>
  <BuildingCivic>
    <CivicType>CIVIC_SOMETHING</CivicType>
    <bValue>1</bValue>
  </BuildingCivic>
  <BuildingCivic>
    <CivicType>CIVIC_ANOTHER</CivicType>
    <bValue>1</bValue>
  </BuildingCivic>
<BuildingCivics>


Since I find the listing of a boolean to be rather silly.


Before you run the .clear() command on something, make sure that it is .size() > 0. Before you run any .___() command on them though, make sure that they aren't == NULL.
 
The value in your m_asz carry over was used to decide WHICH boolean to change. There are only 2 states for any boolean to be, so don't set them equal to anything other than "true" and you should be fine.

You shouldn't need m_abPrereqOrCivicsforPass3, since if the civic was listed at all, then you want to flag it.

Most of my arrays are written for XML looking like:
Code:
<BuildingCivics>
  <BuildingCivic>CIVIC_SOMETHING</BuildingCivic>
  <BuildingCivic>CIVIC_ANOTHER</BuildingCivic>
<BuildingCivics>
Rather than this:

Code:
<BuildingCivics>
  <BuildingCivic>
    <CivicType>CIVIC_SOMETHING</CivicType>
    <bValue>1</bValue>
  </BuildingCivic>
  <BuildingCivic>
    <CivicType>CIVIC_ANOTHER</CivicType>
    <bValue>1</bValue>
  </BuildingCivic>
<BuildingCivics>
Since I find the listing of a boolean to be rather silly.


Before you run the .clear() command on something, make sure that it is .size() > 0. Before you run any .___() command on them though, make sure that they aren't == NULL.

Hmm, okay. I was just basing it off FF code. I honestly have no idea what I'm doing at this point.

So, I should be adding some if statements for the _.clear()'s and _.size()?
 
You should be able to safely clear an empty list, but you should definitely make sure the pointer is not NULL before calling any function on it. If it's NULL, skip the looping too.

Code:
[B][COLOR="Red"]if (m_abPrereqOrCivicsforPass3 && m_aszPrereqOrCivicsforPass3)
{
[/COLOR][/B]	int iNumLoad = m_abPrereqOrCivicsforPass3.size();
	for(iI = 0; iI < iNumLoad; iI++)
	{
		FAssertMsg(GC.getInfoTypeForString(m_aszPrereqOrCivicsforPass3[iI]) >= 0, "Warning, about to leak memory in CvBuildingInfo::readPass3");
		m_pbPrereqOrCivics[GC.getInfoTypeForString(m_aszPrereqOrCivicsforPass3[iI])] [B][COLOR="Red"]=[/COLOR][/B] m_abPrereqOrCivicsforPass3[iI];
	}
	m_aszPrereqOrCivicsforPass3.clear();
	m_abPrereqOrCivicsforPass3.clear();
[B][COLOR="Red"]}[/COLOR][/B]

I thought the reason for having the boolean fields in the XML was so that you could have a module remove a civic prereq by specifying 0.
 
Hmm. Adding those if's that EF posted just caused some compiler errors.

error C2676: binary '&&' : 'std::vector<_Ty,_Ax>' does not define this operator or a conversion to a type acceptable to the predefined operator
1> with
1> [
1> _Ty=bool,
1> _Ax=std::allocator<bool>
1> ]

I figured they should have the parenthesis, and added them, but it didn't fix the error, just gave me a different one.

error C2064: term does not evaluate to a function taking 0 arguments
 
Back
Top Bottom