Game Development Community

VectorPtr changing StringTableEntry?

by Justin Mosiman · in Torque Game Builder · 04/22/2009 (10:57 pm) · 4 replies

Hello,

When the user clicks a button, I want a unit to spawn after a set amount of time. The user can click the button multiple times before the first unit spawns, so I need to store the spawning status in a queue.

I have all of that information stored in a struct (called SpawnQueueStruct), and one of those pieces of information is the unit's name, stored as a StringTableEntry. The trouble that I am having, is that while no other data values are changing, this name field is changing each time the spawn queue is updated (through a SimEvent). The relevant code is (if I didn't include enough, feel free to ask for more):

The initial addition of the struct to the queue (of type VectorPtr):
SpawnQueueStruct *spawnUnit = new SpawnQueueStruct(unitName,statusBitmap,
														Sim::getCurrentTime() + spawnLength,spawnTime);
	Con::errorf("Name: %s",spawnUnit->mUnitName);
	spawnQueue.push_back(spawnUnit);

	Sim::postEvent( Sim::getRootGroup(), new SpawnQueueEvent(this), Sim::getCurrentTime() + kUpdateInterval );

And each update with the SimEvent:
SpawnQueueStruct *spawnUnit;
	while(iter != spawnQueue.end()){
		spawnUnit = *(iter);
		Con::errorf("Name: %s",spawnUnit->mUnitName);
...
		++iter;
	}

For some reason unknown to me, the name is changing:
Quote:
Name: GroundMeleeUnit
Name: oney: 990
Name: oney: 990
Name: oney: 990
...
I think the "oney: 990" is coming from a GuiTextCtrl on the gui that is completely unrelated to this button/unit (it says "Money: 990"). So obviously it is referencing a different part of memory, but I have no idea why it is getting a new reference.

Any ideas?

Thanks,
Justin

#1
04/23/2009 (9:26 am)
sounds like you're overwriting memory somewhere. i guess that's obvious.
here's the things i would try:

* change those two debug prints to be different so you can tell which one is printing. (a convenient trick is using the compiler directive __FUNCTION__. eg errorf("%s() - name: %s", __FUNCTION__, name);)

* breakpoint and step through, trying to see where the value changes
- this is easy but unrealiable. it could be getting stomped in totally unrelated code

* i've never used them, but try putting in a data breakpoint.
- this is a breakpoint that will trigger when a memory location changes, no matter what routine changed it. this is obviously the heavy artillery in a situation like this, but it might be worth trying the regular breakpoint approach first as i believe data breakpoints are a bit of a hassle to set up and also make your app run fairly slow. Drew Parker describes how to set them up here.
#2
04/23/2009 (11:18 am)
Thanks for those debug tips, the data breakpoint method was really slick.

It helped me track down the problem, and it is the conversion from script to the engine. My consoleMethod looks like:

ConsoleMethod(SpawnQueue,addToQueue,void,7,7,"(isPlayerOne, unitName, statusBitmap, unitSpawnLength, unitSpawnTime)")
{
	GuiBitmapButtonCtrl *statusBitmap = (GuiBitmapButtonCtrl *)Sim::findObject(argv[4]);
	if(!statusBitmap){
		Con::printf("SpawnQueue::addToQueue: Object "%s" doesn't exist", argv[2]);
		return;
	}

	return object->addToQueue(dAtob(argv[2]),argv[3],statusBitmap,dAtoi(argv[5]),dAtoi(argv[6]));	
}

This method is being called from the script:
$SpawnQueue.addToQueue(%isPlayerOne,%unitName,%statusBitmap,%unitSpawnLength,getSimTime());

In the engine, if I change "argv[3]" to "test", then nothing gets overwritten.

In the script, if I change "%unitName" to "test", then it still gets overwritten.

So it is the conversion from script to c++ - I didn't think anything special was needed to convert text, and looking at other code within the engine this looks like the case, so why am I having problems?

Thank you,
Justin
#3
04/23/2009 (11:31 am)
You can't store the argv[] values that get passed into your ConsoleMethod. They come from a buffer that gets reused for other calls and script type stuff. Try copying argv[3] with dStrdup. Don't forget to dFree() the duplicated string when you're done.

Edit: Or use StringTable->insert(argv[3]). That should do the trick too. And if you do that, don't dFree() it.
#4
04/23/2009 (2:49 pm)
That makes sense, thank you!