I am trying to parallelize my C++ code using Open MP but I am running into Segmentation fault, the serial version is running fine. I used gdb debugger and I know the error is occurring while erasing one of the elements of the STL List.
In the code below I have a vector which contains particle pairs with IDs(boxID1 and boxID2) and each particle has a Actual Contact List associated with it. Then I add and delete if or if not the particles are in contact in a given list.
Is there a way to avoid this error while erasing?
Contact newcontact;
bool isPresentIntheList;
list<Contact>::iterator it;
#pragma omp parallel for private(newcontact, isPresentIntheList, it)
for(long int i=0; i<overlapVector.size(); i++)
{
isPresentIntheList = false;
it = (*particlesPointerVector)[overlapVector[i].boxID2]->ActualContactList.begin();//iterator for Actual Contact List of the particle with ID = overlapVector[i].boxID2
if((*particlesPointerVector)[overlapVector[i].boxID2]->ActualContactList.size() != 0) //if ACL size doesn't have a size = 0
{
for(long int j=0; it!=(*particlesPointerVector)[overlapVector[i].boxID2]->ActualContactList.end(); j++)
{
if(it->particlei->ID == overlapVector[i].boxID1)
{
isPresentIntheList = true;
}
if(isPresentIntheList)
{
if(IsContact(*it, timestep))//checking if the overlapping pair is in contact or not
{
it++;//do nothing that means overlapping pair is in contact
}
else//remove that pair from ACL if it is not in contact
{
{
newcontact.particlei = (*it).particlei;
newcontact.particlej = (*it).particlej;
/*ERROR occurring here*/
it = (*particlesPointerVector)[overlapVector[i].boxID2]->ActualContactList.erase(it);//no it++ required as it automatically points to the next container after erasing
}
}
}
else if(!isPresentIntheList)
it++;
}
}
Related
I want to create a stacking Game. Where when you tap the screen for instance a block falls down and a new one appears where the other one originally was. Now when the User taps the screen again the same block falls down and if aligned correctly stacks on top of the first one so one and so one. Keep stacking until you miss.
I thought creating an array and pushing each new object to that array would be able to hitTest between each new one etc and have them stack on each other. I realized I don't quite understand how to go about doing this. New instances are created so I got that down. Here is my code so far:
private function engineLogic(e:Event):void
{
stackingHandler();
}
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
//HIT TEST CATS
}
trace("NUMBER OF CATS: " + aCatArray.length);
}
private function onTap(e:MouseEvent):void
{
//Move Down
TweenLite.to(cats, 1.0, {y:(stage.stageHeight / 2) + 290, onComplete: addCats});
}
private function addCats():void
{
//Create Instance
cats = new mcCats();
//Add Objects
addChild(cats);
//Push to Array
aCatArray.push(cats);
}
I would appreciate any help from you guys. Maybe if you can push me in the right direction. Thank you in advance!
It looks like the cats variable holds the object that is currently falling?
In that case you'd do something like this:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
if(cats.hitTestObject(aCatArray[i])) {
// collision detected!
// kill the Tween
// set the y position of the `cats` object
// so it appears on top of the object it collided with (`aCatArray[i]`)
// (it may have moved slightly past the object before doing this check)
}
}
}
So you're looping through the array and hit testing cats against every object in the array one at a time.
It might make more sense to use a basic gravity simulation, or just linearly increasing the y value instead of using a Tween, but you didn't ask about that.
You might also want to set a flag for whether or not an object is currently falling and use that to determine whether or not to run the stackingHandler. Otherwise, you'll just be continually hit testing all the objects when nothing is moving.
This is how I was able to fix it. Creating a double for loop. Checking if they are equal to each other continue and check for hitTest:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
for (var j:int = 0; j < aCatArray.length; j++)
{
var newCat:mcCats = aCatArray[j];
if (currentCat == newCat) continue;
//Hit Test between Objects
if (newCat.hitTestObject(currentCat.mcHit) && newCat.bFlag == false)
{
//Stop Moving
newCat.stopMoving();
trace("HIT");
if (highScore == 0)
{
addCats();
trace("ADD CATS 1");
}else
{
TweenLite.delayedCall(0.6, addCats);
trace("ADD CATS 2");
}
//Add Points
highScore ++;
trace(highScore + " Score");
//Set Flag boolean
newCat.bFlag = true
}
}
}
}
I decided to make a simple tool for social networking.
There is a list (in the picture), which has a complex itemRenderer which included two more itemRenderers (IR).
The first (social networks) get data from the global dataProvider, the second (resources) is formed depending on what social network in the first IR selected. The dataProvider of the second IR created on the basis of another dataProvider directly in IR code.
protected function soc_itemClickHandler(event:ItemClickEvent):void
{
if (event.label == 'selected') {
dp = new ArrayCollection();//dataprovider of the second IR
for (var k:int = 0; k < Copypaste.socials.length; k++)
{
for (var j:int = 0; j < Copypaste.resources.length; j++)
{
var socObj:Object = Copypaste.socials.getItemAt(k);
var resObj:Object = Copypaste.resources.getItemAt(j);
if (socObj.selected == true ||socObj.selected == 'true') {
if (resObj.social == socObj.uid) {
dp.addItem(resObj);
}
}
}
}
}
}
All fine, but the problems begin when I want to select another social network - one IR affect the other, the data do not match. And the List can be sorted by dragging of the items, then all the data in the second IR disappear, and the checkboxes in the first IR become disselect.
How to build the architecture of this app?
I've created a simple puzzle game and have uploaded it to kongregate, now I want to upload highscores (the least amount of moves = better) to it using their API. To make sure no one can cheat the system (submitting the score before puzzle is finished) I need to make sure that none of the pieces in the puzzle are black. All the pieces of the puzzle are movieclips and are inside a array called buttons.
I've currently got this:
public function SumbitScore(e:MouseEvent)
{
for (var v:int = 0; v < buttons.length; v++)
{
if (buttons[v].transform.colorTransform.color != 0x000000)
{
_root.kongregateScores.submit(1000);
}
}
}
but I think that will submit the score as soon as it checks a movieclip that is not black and it'll ignore the rest.
I think the way to go is to keep track of whether or not an 'empty button' is found in your for-loop. After the loop you could submit the score if no empty tiles were found or let the player know the puzzle has to be completed before submitting.
I've added some comments in the code below:
// (I changed the function name 'SumbitScore' to 'SubmitScore')
public function SubmitScore(e:MouseEvent)
{
// use a boolean variable to store whether or not an empty button was found.
var foundEmptyButton : Boolean = false;
for (var v:int = 0; v < buttons.length; v++)
{
// check whether the current button is black
if (buttons[v].transform.colorTransform.color == 0x000000)
{
// if the button is empty, the 'foundEmptyButton' variable is updated to true.
foundEmptyButton = true;
// break out of the for-loop as you probably don't need to check if there are any other buttons that are still empty.
break;
}
}
if(foundEmptyButton == false)
{
// send the score to the Kongregate API
_root.kongregateScores.submit(1000);
}
else
{
// I'd suggest to let the player know they should first complete the puzzle
}
}
Alternatively you could let the player know how many buttons he still has to finish:
public function SubmitScore(e:MouseEvent)
{
// use an int variable to keep track of how many empty buttons were found
var emptyButtons : uint = 0;
for (var v:int = 0; v < buttons.length; v++)
{
// check whether the current button is black
if (buttons[v].transform.colorTransform.color == 0x000000)
{
// if the button is empty increment the emptyButtons variable
emptyButtons++;
// and don't break out of your loop here as you'd want to keep counting
}
}
if(emptyButtons == 0)
{
// send the score to the Kongregate API
_root.kongregateScores.submit(1000);
}
else
{
// let the player know there are still 'emptyButtons' buttons to finish before he or she can submit the highscore
}
}
Hope it's all clear.
Good luck!
Has anyone figured out how AS3 actually handles garbage collection? I'm having so many issues releasing memory in a game I'm developing.
Made a small demo:
public class MemoryTesting extends Sprite
{
static protected var list:Array = null;
public function onKeyDown(event:KeyboardEvent):void {
if( event.keyCode == 65 ){ //A key - adds memory
if( list == null ){
list = [];
for( var index:int = 0; index < 10000000; ++index ){
list.push(new Matrix3D());
}
}
}
else{ //Any other key removes memory.
if( list ){
var size:int = list.length;
for( var index:int = 0; index < size; ++index ){
list.pop();
}
list.length = 0;
list = null;
}
System.gc();
}
}
}
Running Flash Player Debugger stand-alone 11.4r402 in Windows 7. Watching the Task Manager, with no keys pressed, the debugger sits idle at 11,000 K.
Pressing a (adding 10Mil Matrix3D classes) takes it up to 962,000 K.
Pressing another key (removing references to the Matrices and nulling the array) depends on how many times I press it.
The first time we call GC - drops to 255,000 K.
The second GC call - 92,000 K.
Third - 52,000 K.
Forth - 42,000 K.
Fifth - 39,000 K.
Sixth & any consecutive times after sits at 38,000 K.
I hear people talking about the GC waiting for "opportune times" to collect. But this is an empty application, not even a enter_frame event and there is no amount of time you can leave it idle for it to remove the remaining 27,000 K (38,000 - 11,000).
Sitting at the new low, if we re-add the matrices we move back up to 975,000 K.
That is to say, 13,000 K more than the first time. If I repeat this add/remove, it stays the same, going back up to 975,000 K and down to 38,000 K.
Remember, there is nothing going on in this application. My actual application has 650mb of raw bitmap data, let alone 100mb of SWF to parse and 500mb of XML classes that I only use in initialisation code.
I've read multiple times that even calling GC manually is bad, let alone 6 times. But none of the Matrix3D's will be released if I don't.
How does anyone handle this? Shall I just call GC 6 times at the end of initialisation?
Edit:
I was testing in release mode for differences and whether, without the System.gc() call, that if it doesn't free the memory from flash, at the least re-uses it properly. It does eventually, but with a new, higher footprint. With a full list sits at 990,000 K, clearing it takes it to 1,050,000 K.
This is for data that initially cost us 962,000 K RAM. That's 90MB of weird internal flash GC memory. Let alone ignoring that it won't ever give the memory back to the OS (without the explicit GC calls).
Actionscript's GC is weird, nothing to say,
If you'll try to use something like this, it helps (I just tested and GC clears out the memory on the very first try (key click)), Just changed Array to Vector to test more quicker, just the same should happen with Array too. My enviroment is FlashCC in this case.
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.geom.Matrix3D;
import flash.net.LocalConnection;
import flash.system.System;
import flash.utils.setTimeout;
public class MemoryTesting extends Sprite
{
var list:Vector.<Matrix3D> = null;
function MemoryTesting()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
public function onKeyDown(event:KeyboardEvent):void
{
var matrx:Matrix3D;
var index:int
if (event.keyCode == 13)
{
trace(System.totalMemory, "starting to fill...")
if (list == null)
{
list = new Vector.<Matrix3D>
for (index = 0; index < 1000000; ++index)
{
matrx = new Matrix3D();
list.push(matrx);
}
}
trace(System.totalMemory, " done...")
}
else
{
if (list)
{
trace(System.totalMemory, " preparing to delete...")
list.splice(0, list.length);
list = null;
}
//force GC to work normally, it really helps (at least in my case)
try
{
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
}
catch (e:*)
{
}
setTimeout(function()
{
trace(System.totalMemory, " deleted")
}, 50)
}
}
}
}
This strange snippet really helps on most cases
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
Here is the freat article:
http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html
I'm sorry if it's asking for too much, but I'm too confused by now. I'm making this really simple shooter game for my nephew in AS3. It all seems to be working just fine, except for one really annoying error that keeps popping up every second or third time the game is launched.
IT is Error #1009: Cannot access a property or method of a null object reference. The problem is always with parent.removeChild(this) command in the relevant class (EnemyClass, BulletClass or MissileClass). This happens in two cases: either when checkFinishConditions method in Main is called and the EnemyClass instance needs to be deleted. So if I get the #1009 error does this mean the instance has already been deleted? The second situation is when inst.hitTestObject(enemyInstance) is checked in Main class. Does this mean the EnemyClass instance has already been deleted somehow? I'm totally lost here to be honest.
private function checkCollision():void
{
//loop through missiles
for (var i:int = 0; i < aMissileArray.length; i++) {
//get the current missile
var currentMissile:missileClass = aMissileArray[i];
//loop through enemies
for (var j:int = 0; j < aEnemyArray.length; j++) {
var thisEnemy:EnemyClass = aEnemyArray[j];
if (currentMissile.hitTestObject(thisEnemy)) {
var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);
addChild(thisExplode);
currentMissile.destroyThis();
aMissileArray.splice(i,1);
thisEnemy.deleteEnemy();
aEnemyArray.splice(j, 1);
aDamageArray.splice(j, 1);
scoreValueText += 1;
j--;
i--;
}
//break;
}
}
//loop through bullets
for (var l:int = 0; l < aBulletArray.length; l++) {
//get the current missile
var currentBullet:BulletClass = aBulletArray[l];
//loop through enemies
for (var k:int = 0; k < aEnemyArray.length; k++) {
var currentEnemy:EnemyClass = aEnemyArray[k];
if (currentBullet.hitTestObject(currentEnemy)) {
currentBullet.destroyThis();
aBulletArray.splice(l, 1);
aDamageArray[k] -= 1;
l--;
if (aDamageArray[k] < 1) {
//create an explosion
var thisBulletExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);
addChild(thisBulletExplode);
currentEnemy.deleteEnemy();
aEnemyArray.splice(k, 1);
aDamageArray.splice(k, 1);
scoreValueText += 1;
k--;
}
break;
}
}
}
}
There is alot of code to look over, but one potential issue I see is here :
for each(var currentDieEnemy:EnemyClass in aEnemyArray) {
aEnemyArray.splice(0, 1);
currentDieEnemy.deleteEnemy();
}
The potential issue is that you are 'assuming' that the order of this loop is sequential based on the actual index order of the Array. You might want to stick a trace in there to verify that is actually what is happening, because I believe it's possible that they can be out of order.
See this question for details -- For-Each Loop AS3: Is the direction guaranteed?
So imagine the scenario where the 3rd item in the array is first and you splice the item at the 0 index. Now, you have an item in the array that is removed from the display list, but not from the array. So what happens when you get to that item ? Pretty much what you are describing will happen since the parent property is null, since you already removed it from the display list.
The way to fix that is to do something like this :
while (aEnemyArray.length > 0)
{
var currentDieEnemy:EnemyClass = aEnemyArray[0];
currentDieEnemy.deleteEnemy();
aEnemyArray.splice(0,1);
}
I found another issue in this block of code :
for (var j:int = 0; j < aEnemyArray.length; j++) {
var thisEnemy:EnemyClass = aEnemyArray[j];
if (currentMissile.hitTestObject(thisEnemy)) {
var thisExplode:ExplosionClass = new ExplosionClass(thisEnemy.x,thisEnemy.y);
addChild(thisExplode);
currentMissile.destroyThis();
aMissileArray.splice(i,1);
thisEnemy.deleteEnemy();
aEnemyArray.splice(j, 1); // now array composition is different.
aDamageArray.splice(j, 1);
scoreValueText += 1;
}
}
When you loop through an Array and splice an item at the loop index, you have to realize what happens to the composition of the array. Here's an example
Suppose enemy3 needs to be spliced because of a collision. Given your code, this is what happens :
Before (j == 2)
(0) enemy1
(1) enemy2
(2) enemy3
(3) enemy4
(4) enemy5
AFTER
(0) enemy1
(1) enemy2
(2) enemy4
(3) enemy5
So when the loop continues, j will now increment and equal 3.
The result is that enemy4 doesn't get evaluated as the composition of the array collapses to fill the hole created by the splice and you didn't adjust your loop index variable.
So, what you can do in that situation is simply decrement the loop index variable at the end of the block like so :
aEnemyArray.splice(j, 1); // now array composition is different.
aDamageArray.splice(j, 1);
scoreValueText += 1;
j--; // decrement loop index variable.
So while this is one solution, the main point to take away here is the change in the composition of your Array after a splice.
Yep, you are splicing your objects from arrays in a weird way. First, you are traversing the array forwards and splicing in the loop. This can lead to issues of several bullets not trigger collisions when they should, or say not move. See, if you are running your loop for bullets at index i, once you call bullets.splice(i,1); the bullet that was to be iterated next becomes at position i, then you increment i and that bullet remains unprocessed.
Next, you have nested loops, and in the inner loop you are removing an object from OUTER loop. This means once you did a removal of the outer loop's object, your inner loop is now invalidated, you have to preemptively terminate inner loop.
//loop through bullets
for (var l:int = aBulletArray.length-1; l>=0; l--) {
// first, traverse both arrays backwards
//get the current missile
var currentBullet:BulletClass = aBulletArray[l];
//loop through enemies
for (var k:int = aEnemyArray.length-1; k>=0; k--) {
var currentEnemy:EnemyClass = aEnemyArray[k];
if (currentBullet.hitTestObject(currentEnemy)) {
currentBullet.destroyThis();
aBulletArray.splice(l, 1);
aDamageArray[k] -= 1;
if (aDamageArray[k] < 1) {
//create an explosion
var thisExplode:ExplosionClass = new ExplosionClass(currentEnemy.x,currentEnemy.y);
addChild(thisExplode);
currentEnemy.deleteEnemy();
aEnemyArray.splice(k, 1);
aDamageArray.splice(k, 1);
scoreValueText += 1;
}
// and since we don't have "currentBullet" anymore, do this
break;
}
}
}
Fix all the other iterations through your arrays where you do splicing, like I did in this part of code, and you should avoid 1009 errors in these loops.
Also, you should not post your entire project code, but instead post only relevant parts, say an entire function that's reported as throwing an error, and explain which line is producing the error - it's written as number in the error's stack trace.