Debugging a release only flash issue
I've got an Adobe Flash 10 program that freezes in certain cases, however only when running under a release version of the flash player. With the debug version, the application works fine.
What are the best approaches to debugging such issues? I considered installing the release player on my computer and trying to set some kind of non-graphical method of output up (I guess there's some way to write a log file or similar?), however I see no way to have both the release and debug versions installed anyway :( .
EDIT: Ok I managed to replace my version of flash player with the release version, and no freeze...so what I know so far is:
Flash: Debug Release
Vista 32: works works
XP PRO 32: works* freeze
- I gave them the debug players I had to test this
Hmm, seeming less and less like an error in my code and more like a bug in the player (10.0.45.2 in all cases)... At the very least id like to see the callstack at the point it freezes. Is there some way to do that without requiring them to install various bits and pieces, e.g. by letting flash write out a log.txt or something with a "trace" like function I can insert in the code in question?
EDIT2: I just gave the swf to another person with XP 32bit, same results :(
EDIT3: Ok, through extensive use of flash.external.ExternalInterface.call("alert", "..."); I managed to find the exact line causing the problem (I also improved exception handling code so rather than freeze it told me there was an "unhandled" exception). The problem now is what on earth is flashes problem with this with the release player on some machines...
particles.push(p);
Which causes a TypeError #1034 on said platforms. Particles is a Vector.<Particle>, p is a Particle. I tested with getQualifiedClassName and got:
getQualifiedClassName(p) = ::Particle
getQualifiedClassName(particles) = __AS3__.vec::Vector.<::Particle>
Any ideas why this is a problem and what to do to make it work?
EDIT4:
Ok I seem to have solved this. The Particle class is just a simple internal class located after the package {...} in the action script file using it. I moved this into its own file (particle.as) and made it a proper public class in my package, and problem solved.
Maybe its a flash bug or maybe I missed the memo about not using internal classes in vectors or something, although 开发者_开发百科if that's the case I would have expected something or other (either at compile time or with debug runtimes) to disallow it explicitly, e.g. some error on the "private var particles:Vector.<Particle>;" line. If I get a chance I guess I'll take a look at contacting the Adobe flash team concerning this or something.
Thanks for help giving debugging tips which I guess is more along the original questions lines :)
This is a long shot, but are the Particles the objects that you are clicking? If so then catching the event in the wrong phase of bubbling, and pushing event.target (assuming it to be a Particle) could cause that problem.
Whatever the problem, I have something that should help you debug. A class that creates a pseudo trace window in your SWF, much nicer than extinterfacing to javascript. I've forgotten who wrote it, but I feel like it's Senocular. I use it any time I need to get traces back from end users.
Just drop it in the default package for your project, call stage.addChild(new Output());, and then to trace call Output.trace("A message");
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.GradientType;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import flash.text.TextFieldAutoSize;
/**
* Creates a pseudo Output panel in a publish
* swf for displaying trace statements.
* For the output panel to capture trace
* statements, you must use Output.trace()
* and add an instance to the stage:
* stage.addChild(new Output());
*
*/
public class Output extends Sprite {
private var output_txt:TextField;
private var titleBar:Sprite;
private static var instance:Output;
private static var autoExpand:Boolean = false;
private static var maxLength:int = 1000;
public function Output(outputHeight:uint = 400){
if (instance && instance.parent){
instance.parent.removeChild(this);
}
instance = this;
addChild(newOutputField(outputHeight));
addChild(newTitleBar());
addEventListener(Event.ADDED, added);
addEventListener(Event.REMOVED, removed);
}
// public methods
public static function trace(str:*):void {
if (!instance) return;
instance.output_txt.appendText(str+"\n");
if (instance.output_txt.length > maxLength) {
instance.output_txt.text = instance.output_txt.text.slice(-maxLength);
}
instance.output_txt.scrollV = instance.output_txt.maxScrollV;
if (autoExpand && !instance.output_txt.visible) instance.toggleCollapse();
}
public static function clear():void {
if (!instance) return;
instance.output_txt.text = "";
}
private function newOutputField(outputHeight:uint):TextField {
output_txt = new TextField();
//output_txt.type = TextFieldType.INPUT;
output_txt.border = true;
output_txt.borderColor = 0;
output_txt.background = true;
output_txt.backgroundColor = 0xFFFFFF;
output_txt.height = outputHeight;
var format:TextFormat = output_txt.getTextFormat();
format.font = "_sans";
output_txt.setTextFormat(format);
output_txt.defaultTextFormat = format;
return output_txt;
}
private function newTitleBar():Sprite {
var barGraphics:Shape = new Shape();
barGraphics.name = "bar";
var colors:Array = new Array(0xE0E0F0, 0xB0C0D0, 0xE0E0F0);
var alphas:Array = new Array(1, 1, 1);
var ratios:Array = new Array(0, 50, 255);
var gradientMatrix:Matrix = new Matrix();
gradientMatrix.createGradientBox(18, 18, Math.PI/2, 0, 0);
barGraphics.graphics.lineStyle(0);
barGraphics.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, gradientMatrix);
barGraphics.graphics.drawRect(0, 0, 18, 18);
var barLabel:TextField = new TextField();
barLabel.autoSize = TextFieldAutoSize.LEFT;
barLabel.selectable = false;
barLabel.text = "Output";
var format:TextFormat = barLabel.getTextFormat();
format.font = "_sans";
barLabel.setTextFormat(format);
titleBar = new Sprite();
titleBar.addChild(barGraphics);
titleBar.addChild(barLabel);
return titleBar;
}
// Event handlers
private function added(evt:Event):void {
stage.addEventListener(Event.RESIZE, fitToStage);
titleBar.addEventListener(MouseEvent.CLICK, toggleCollapse);
fitToStage();
toggleCollapse();
}
private function removed(evt:Event):void {
stage.removeEventListener(Event.RESIZE, fitToStage);
titleBar.removeEventListener(MouseEvent.CLICK, toggleCollapse);
}
private function toggleCollapse(evt:Event = null):void {
if (!instance) return;
output_txt.visible = !output_txt.visible;
fitToStage(evt);
}
private function fitToStage(evt:Event = null):void {
if (!stage) return;
output_txt.width = stage.stageWidth;
output_txt.y = stage.stageHeight - output_txt.height;
titleBar.y = (output_txt.visible) ? output_txt.y - titleBar.height : stage.stageHeight - titleBar.height;
titleBar.getChildByName("bar").width = stage.stageWidth;
}
}
}
Judging by when the freeze occurs, try to pinpoint some possibilities for what the offending code may be, and use De MonsterDebugger to check variables etc.
EDIT: I'm pretty certain that the actual call stack is only available to you in the debug versions of the Flash Player / AIR. Still, it may be useful in the debug player to trace the stack from within the handler for the button to see if anything is out of place:
var err:Error = new Error(“An Error”);
trace(err.getStackTrace());
FYI the getStackTrace method is only available in the debug player, so there is no way to write it to a log.txt in production.
精彩评论