C++/Cli Destructors are not called - constructor

I am trying to investigate a memory leak problem and I found out that destructors in my library are not even called and I have the following code:
PPCamNET::Native::PpQueue::PpQueue(int capacity) : m_capacity(capacity), m_array(nullptr), m_head(0), m_tail(0)
{
// Quick fix for case when capacity is 1 (single snap)
// and Push function crashes on 1st frame
if (m_capacity == 1)
m_capacity = 2;
m_array = new FrameData[m_capacity];
m_pushes = 0;
m_pops = 0;
}
The above constructor's destructor should be called after PpQueue is destroyed, but it is not stopping at the break point.
PPCamNET::Native::PpQueue::~PpQueue()
{
delete[] m_array; //<==== here I set a break point
}
PPQueue instance is created by AcqCache constructor.
PPCamNET::Internal::AcqCache::AcqCache(AcqBuffer^ acqBuffer)
{
//m_stopWatchPush = Stopwatch::StartNew();
//m_stopWatchPop = Stopwatch::StartNew();
m_acqBuffer = acqBuffer;
m_cacheLock = gcnew Object();
m_processFrameRunning = true;
try
{
m_frameDataCache = new PpQueue(acqBuffer->BufferSize / 2 + 1);
AcqCache destructor removes m_frameDataCache, which is PpQueue.
PPCamNET::Internal::AcqCache::~AcqCache()
{
m_processFrameRunning = false;
delete m_frameDataCache; // <== here another break point but not called
delete[] m_frameInfoBuffer;
}
Finally the constructor of Acqusition creates an instance of m_acqCache with gcnew.
PPCamNET::Internal::Acquisition::Acquisition(AcqBuffer^ acqBuffer,
CameraSettings^ camSettings)
{
m_eofEvent = gcnew AutoResetEvent(false);
m_acqCache = gcnew AcqCache(acqBuffer);
I am puzzled why these destructors aren't called. Is this because GC didn't kick in to clear up m_acqCache causing other desructors not being called ?
Thanks,

GC will not call a destructor. The C++/CLI compiler translates destructors into IDisposable::Dispose() implementation, and has a different syntax (ClassName::!ClassName) which gets translated to Finalize.
C# wrongly confuses this issue by using the name "destructor" for the CLR Finalize function. Finalizers are not deterministic. The Dispose() function is not called automatically by GC. Not difficult once you know what's going on, but the terminology sure leads to confusion.

Related

Actions with a list of instances - AS3

what is the best way to do an action with many instances at the same time?
Lets say I have 50 movieclip instances called A1 to A50, and I want to run an action with only A20 to A35.
For example:
(A20-A35).gotoAndStop(2)
You want an algorithm operation called loop. You are not able to abstractly address things in bunches at once, but you can loop and iterate the bunch one by one which produces basically the same result. Please read this: https://en.wikipedia.org/wiki/Control_flow#Loops When you need to do a quantity of similar operations it is always loop.
With regard to your problem:
// Loop iterator from 20 to 35 inclusive.
for (var i:int = 20; i <= 35; i++)
{
trace("");
// Compose the name of the MovieClip to retrieve.
var aName:String = "A" + i;
trace("Retrieving the MovieClip by name", aName);
// Retrieve the instance by its instance name.
var aChild:DisplayObject = getChildByName(aName);
// Sanity checks about what exactly did you find by that name.
if (aChild == null)
{
// Report the essence of the failure.
trace("Child", aName, "is not found.");
// Nothing to do here anymore, go for the next i.
continue;
}
else if (aChild is MovieClip)
{
// Everything is fine.
}
else
{
// Report the essence of the failure.
trace("Child", aName, "is not a MovieClip");
// Nothing to do here anymore, go for the next i.
continue;
}
// Type-casting: tell the compiler that the child is actually
// a MovieClip because DisplayObject doesn't have gotoAndStop(...)
// method so you will get a compile-time error even if you are
// sure the actual object is a valid MovieClip and definitely has
// the said method. Compile-time errors save us a lot of pain
// we would get from run-rime errors otherwise, so treasure it.
var aClip:MovieClip = aChild as MovieClip;
trace(aClip, "is a MovieClip and has", aClip.totalFrames, "frames.");
if (aClip.totalFrames < 2)
{
// Nothing to do here anymore, go for the next i.
continue;
}
// Now you can work with it.
aClip.gotoAndStop(2);
}
Now that you understand the while idea step by step, if you are sure all of them are present and all of them are MovieClips you can go for a shorter version:
for (var i:int = 20; i <= 35; i++)
{
(getChildByName("A" + i) as MovieClip).gotoAndStop(2);
}
UPD: You can as well address children with square bracket access operator.
for (var i:int = 20; i <= 35; i++)
{
// You can skip type-casting as this["A" + i] returns an untyped reference.
this["A" + i].gotoAndStop(2);
}
Yet there are differences and complications. Method getChildByName(...) always returns a DisplayObject with the given name (or null if none found). Square brackets operator returns an untyped OOP field of the current object.
It will not work with dynamically added children (unless you pass their references to the respective fields).
It will not work if "Automatically Declare Stage Instances" publish option is off.
Finally, this["A" + 1] and A1 are not exactly the same because the latter could refer to a local method variable rather than object member.
I'm not saying that square brackets are evil, they're as fine, yet, as always, programming is not a magick thus understanding what you are doing is the key.

Ask how to give jProgressBar for my iteration

I want to ask how to give jProgressBar in my code. i used netbeans interface. progressBar will end after it reach maximum_iteration.
jProgressBar already in other class. how can i fix it? Thank you. Please help.
train() is placed in other class.
public void train(){
for(int iteration=0; iteration<this.max_iteration; iteration++){
//int percent = (iteration/this.max_iteration) * 100;
//cs.jProgressBar1.setValue(percent);
for(int index=0; index<this.hms; index++){
Node[] newChord = {};
double random = Math.random();
/*process HS*/
if(this.original_chord != null){
// ensure the fist note of the new chord is not altered
newChord[0].notes = new int[first_chord_notes.length];
for(int j=0; j<first_chord_notes.length; j++){
newChord[0].notes[j] = first_chord_notes[j];
}
}
// evaluate new chord and substitute the worst one in hs if new chord is better
double newFitness = this.nodeListFitness(this.original_chord, newChord);
int worstIndex = this.worst_index();
double worstFitness = this.fitness[worstIndex];
if(newFitness > worstFitness){
this.hm[worstIndex] = newChord;
this.fitness[worstIndex] = newFitness;
}
}
System.out.println("Harmony Memory " + (iteration+1));
this.debug();
System.out.println("");
//JProgressBar jProgressBar1 = new JProgressBar();
//cs.jProgressBar1.setValue(iteration);
//cs.jProgressBar1.setEnabled(true);
}
}
I'm not sure at 100% but a Swing Component can be updated only inside the EventDispatcherThread, which is the Thread that run the GUI. For this reason, it will probably be better that you call the method train() inside you GUI, so it run into the EDT. Also, I can't understand why do you call the constructor of the JProgessBar, if you say that it is already in other class, probably the other class (I image it is the GUI) has already created a new instance of the progress bar.

Actionscript3 to Arduino: sending a 'newline' character after an array of integers

I want to send an array of integers from an as3 app I'm writing in Flash Pro, to an Arduino Uno which will use them to continuously position and re-position 5 servos. So sending 15 integers will position the 5 servos, then re-position them, then reposition them again, then loop back to the first position and so on. Then I would send a new array replacing the old one whenever I wanted to.
So I've got my tinkerproxy configured between them ok (thanks to Mike Chambers and others) and I've written both sides so they appear to work ok when interfacing with their serial monitors. But I can't get em talking to each other properly.
My problem is simple ... I think ... It's how to get as3 to send a 'newline' or some other 'end' signal with or after the array so that the Arduino sketch (using serialEvent and parseInt to get the integers when they are sent), on receiving it, can jump past parseInt and do something else - in this case go to the loop and control these pesky servos.
Probably far too much code attached and I hope somebody can help. I'm pretty inexperienced, you may have guessed....
ARDUINO
/*
this sketch developed from arduino Tutorials ReadASCIIString + SerialEvent
serialEvent can receive an array - 'buff' - of values from serial monitor
loop can get those values and print some of them to prove it
but I can't get Flash Pro (as3) to send the array: something to do with end of message character?
*/
#include <Servo.h>
int buff[100];//an array to hold integers from serial(arbitrary larger than ever needed size)
int j; //used to increment serial integer receipt in serialEvent
int patternLength;//=# of integers delivered over serial port, if followed by E or newline
void setup()
{
Serial.begin(9600);
Serial.setTimeout(2147483647);//25 days! so parseInt doesn't default to sending zeros every second
Serial.println("ready to go");//prints ok
}
void loop()
{
for(int i=0; i<patternLength-4; i=i+5)//feed sets of 5 integers into 5 servos then repeats
Serial.println(buff[i]);//prints 1st, 5th, 10th etc integer then repeats
delay(1000);//so I can see it happening slowly enough
}//loops indefinitely until serialEvent interrupts to send new buff array values
void serialEvent()
{
while(Serial.available()>0)
{
buff[j] = Serial.parseInt();
Serial.println(buff[j]);//prints all integers sent if eg ','sent after last one
j++;
//if (Serial.read() == '\n')//works if serial monitor is set to 'newline' on sending
if (Serial.read() == 'E')//works if no 'newline' + sending eg 1,2,3,4,5,6,7,8,9,10E
//BUT how to send the equivalent of one of the above two 'endings' from Flash???
//so that this part of the code executes
{
patternLength = j;
Serial.println("go to loop");
j=0;//reset the index so next array sent replaces this one in 'buff'
}
}
}
FLASH PRO ACTIONSCRIPT as3
/*
Simple Example that connects to an Arduino (via TinkerProxy) and sends
an array of integers for it to use. That doesn't work......
adapted from FlashBlink Created by Mike Chambers:
http://www.mikechambers.com/blog/2010/08/04/getting-started-with-flash-and-arduino/
*/
import flash.events.Event;
import flash.display.Sprite;
import flash.net.Socket;
//import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
//import flash.events.SecurityErrorEvent;
import flash.utils.Endian;
import flash.events.MouseEvent;
//my example of an array of integers I want to send to the arduino
var pattern:Array = [10,11,12,13,14,15,16,17,18,19,20];
//socket we will use to connect to TinkerProxy
var _socket:Socket;
//Address where TinkerProxy is located. Will usually be
//localhost / 127.0.0.1
var _proxyAddress:String = "127.0.0.1";
//port TinkerProxy is listening on
var _proxyPort:uint = 5331;
function onAddedToStage():void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
//create a Sprite to add to the stage.
//This will be a simple button
var s:Sprite = new Sprite();
//draw a green square in the Sprite
s.graphics.beginFill(0x00FF00);
s.graphics.drawRect(0,0, 200,100);
s.graphics.endFill();
//Add Sprite to the display list
addChild(s);
//position it
s.x = 50;
s.y = 50;
//listen for when the user clicks the Sprite
s.addEventListener(MouseEvent.CLICK, onClick);
_socket = new Socket();
//Register for socket events
//socket connected
_socket.addEventListener( Event.CONNECT, onConnect );
//socket closed
_socket.addEventListener( Event.CLOSE, onClose );
_socket.endian = Endian.LITTLE_ENDIAN;
//connect
_socket.connect(_proxyAddress, _proxyPort);
}
//called when we connect to the proxy server
function onConnect(event:Event):void
{
trace("Socket Connected");
}
//called when the user clicks the button on stage
function onClick(event:MouseEvent):void
{
trace("onClick");
//make sure we are connected to the socket
if(!_socket.connected)
{
//if not, don't do anything
trace("You must be connected to send a command to the Arduino.");
return;
}
var ENDOF:String = "E";
for(var j:int = 0; j < pattern.length; j++)
{
_socket.writeUTFBytes(pattern[j]); //send pattern array to Arduino
trace(pattern[j]);//trace what I think I've just sent
}
//then send something as a last character - not an integer.
_socket.writeUTFBytes(ENDOF);//send this string value to arduino
trace("should have just sent an E, and sends an: " + ENDOF);
//but how do I send this E conjoined to the last integer of the pattern array
//so that Arduino responds by jumping out of serialEvent back to the loop?
//flush the socket. Not really necessary, but here for forward compatibility.
_socket.flush();
}
//called when the socket is closed
function onClose(event:Event):void
{
trace("Socket Closed");
}
onAddedToStage();
Your AS3 looks fairly spot on. One minor point, in onAddedToStage() you're removing an event listener from the stage which you never registered for. If you really want that code to only fire once the timeline is added to the stage, replace line 114 with with following:
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage)
As for your Arduino code , I'm not versed in the language it uses (some sort of C?), so feel free to ignore the following if you know better.
You didn't encapsulate your for loop on lines 22 thru 24
You started encapsulating your while loop on line 30, but forgot to close it on line 34
You declared j, but didn't initialized its value until line 44 after it was to be used in your while loop on line 33.
Finally, to answer your core question. You're already aware a newline is written as \n, so it would seem you're having difficulty reading this from Serial.read(). After reading the documentation, I couldn't find any datatype it comes out as, so I'm assuming you're dealing with either a ByteArray or a String. Assuming it's a string, my first instinct would be to just split it into an Array with String.split(), but that's not a function available to String API. Others (however) have written it, and I believe it would simplify the issue, assuming Strings & Ints can happily co-exist in those object types.
Conversely, since you already know the size of these numbers come in quintets, rather than use a while loop (line 29), you could just use a for as follows:
#include <Servo.h>
int buff[100];
int j;
int patternLength;
void setup() {
Serial.begin(9600);
Serial.setTimeout(2147483647);
Serial.println("ready to go");
}
void loop() {
for(int i=0; i<patternLength-4; i=i+5) {
Serial.println(buff[i]);
delay(1000);
}
}
void serialEvent() {
if (Serial.available() > 0) {
// This gaurantees we only pull the first 15 Ints into our buff array
for (int k=0; k<15; k++) {
buff[j] = Serial.parseInt();
Serial.println(buff[j]);
j++;
}
patternLength = j;
Serial.println("go to loop");
j=0;//reset the index so next array sent replaces this one in 'buff'
}
}
If the above misses the mark for you, you may want to debug the value you're actually reading from the Stream and testing for in your if statement on line 37 with:
Serial.println("Reading: " + Serial.read());
Hope it helps.
-Cheers

Supplied DisplayObject must be a child of the caller

I get this error once in a while for a specific object. For some reason, this issue seems to start when I spawn 2 of this object instead of one. I basically have enemies that drops coins and one enemy drops 2. When I pick them up at the same time I start getting this error.
public function removeCoin(){
removeEventListener(Event.ENTER_FRAME, moveCoin);
if(this.parent){
this.parent.removeChild(this);
}
parentMC.level.spawnedCoins.splice(this, 1);
}
This is the function called by the collision check when there is a collision between the player and the coin. The issue usually starts when I pick up two coins at once from this function.
var dropCoin:Number = Math.random() * 100;
if(dropCoin > 40){
var newCoin1:coin = new coin(parentMC);
var newCoin2:coin = new coin(parentMC);
newCoin1.x = x+7;
newCoin1.y = y;
parentMC.level.levelObjects.addChild(newCoin1);
parentMC.level.spawnedCoins.push(newCoin1);
newCoin2.x = x-7;
newCoin2.y = y;
parentMC.level.levelObjects.addChild(newCoin2);
parentMC.level.spawnedCoins.push(newCoin2);
}
Edited the code.
That error means that the item you're trying to remove from the display list (by calling removechild) either isn't on the display list, or isn't a child of the object your calling removeChild on.
Without analyzing all your code, a quick check can fix your problem likely.
Change you existing chunk of code:
if(this != null){
parentMC.lvl1.levelObjects.removeChild(this);
}
to this:
if(this.parent){
this.parent.removeChild(this);
}
This checks if 'this' has a parent, if so, it removes itself from it's parent.
I think your problem might be:
parentMC.level.spawnedCoins.splice(this, 1);
If spawnedCoins is just an array then splice should take 2 integer args startIndex and deleteCount relevant adobe help page
By passing an object what I think is happening is that it is casting the object to an int, value of '1' (i.e. not null).
What I think you want instead is parentMC.level.spawnedCoins.splice(parentMC.level.spawnedCoin.indexOf(this), 1);

Segfault Copy Constructor

My code is as follows:
void Scene::copy(Scene const & source)
{
maxnum=source.maxnum;
imagelist = new Image*[maxnum];
for(int i=0; i<maxnum; i++)
{
if(source.imagelist[i] != NULL)
{
imagelist[i] = new Image;
imagelist[i]->xcoord = source.imagelist[i]->xcoord;
imagelist[i]->ycoord = source.imagelist[i]->ycoord;
(*imagelist[i])=(*source.imagelist[i]);
}
else
{
imagelist[i] = NULL;
}
}
}
A little background: The Scene class has a private int called maxnum and an dynamically allocated Array of Image pointers upon construction. These pointers point to images. The copy constructor attempts to make a deep copy of all of the images in the array. Somehow I'm getting a Segfault, but I don't see how I would be accessing an array out of bounds.
Anyone see something wrong?
I'm new to C++, so its probably something obvious.
Thanks,
I would suggest that maxnum (and maybe imagelist) become a private data member and implement const getMaxnum() and setMaxnum() methods. But I doubt that is the cause of any segfault the way you described this.
I would try removing that const before your reference and implement const public methods to extract data. It probably compiles since it is just a reference. Also, I would try switching to a pointer instead of pass by reference.
Alternatively, you can create a separate Scene class object and pass the Image type data as an array pointer. And I don't think you can declare Image *imagelist[value];.
void Scene::copy(Image *sourceimagelist, int sourcemaxnum) {
maxnum=sourcemaxnum;
imagelist=new Image[maxnum];
//...
imagelist[i].xcoord = sourceimagelist[i].xcoord;
imagelist[i].ycoord = sourceimagelist[i].ycoord;
//...
}
//...
Scene a,b;
//...
b.Copy(a.imagelist,a.maxnum);
If the source Image had maxnum set higher than the actual number of items in its imagelist, then the loop would run past the end of the source.imagelist array. Maybe maxnum is getting initialized to the value one while the array starts out empty (or maxnum might not be getting initalized at all), or maybe if you have a Scene::remove_image() function, it might have removed an imagelist entry without decrementing maxnum. I'd suggest using an std::vector rather than a raw array. The vector will keep track of its own size, so your for loop would be:
for(int i=0; i<source.imagelist.size(); i++)
and it would only access as many items as the source vector held. Another possible explanation for the crash is that one of your pointers in source.imagelist belongs to an Image that was deleted, but the pointer was never set to NULL and is now a dangling pointer.
delete source.imagelist[4];
...
... // If source.imagelist[4] wasn't set to NULL or removed from the array,
... // then we'll have trouble later.
...
for(int i=0; i<maxnum; i++)
{
if (source.imagelist[i] != NULL) // This evaluates to true even when i == 4
{
// When i == 4, we're reading the xcoord member from an Image
// object that no longer exists.
imagelist[i]->xcoord = source.imagelist[i]->xcoord;
That last line will access memory that it shouldn't. Maybe the object still happens to exist in memory because it hasn't gotten overwritten yet, or maybe it has been overwritten and you'll retrieve an invalid xcoord value. If you're lucky, though, then your program will simply crash. If you're dealing directly with new and delete, make sure that you set a pointer to NULL after you delete it so that you don't have a dangling pointer. That doesn't prevent this problem if you're holding a copy of the pointer somewhere, though, in which case the second copy isn't going to get set to NULL when you delete-and-NULL the first copy. If you later try to access the second copy of the pointer, you'll have no way of knowing that it's no longer pointing to a valid object.
It's much safer to use a smart pointer class and let that deal with memory management for you. There's a smart pointer in the standard C++ library called std::auto_ptr, but it has strange semantics and can't be used in C++ containers, such as std::vector. If you have the Boost libraries installed, though, then I'd suggest replacing your raw pointers with a boost::shared_ptr.