如何调试运行时堆栈下溢错误?

12

我正在努力解决一个堆栈下溢的问题。运行时我得到的回溯是:

VerifyError: Error #1024: Stack underflow occurred.
at flash.events::EventDispatcher/dispatchEventFunction() at flash.events::EventDispatcher/dispatchEvent() at flash.net::URLLoader/onComplete()

这特别难以调试,因为在调试模式下运行时根本不会发生。它只会在编译为发布版时发生。

有人有关于如何调试堆栈下溢的提示吗?或者有一个干净的解释可以用于Flash吗?

如果有帮助的话,当我单击一个处理程序使RPC调用的按钮时,就会出现此错误,该调用使用URLLoader、AsyncToken,然后调用与AsyncToken相关联的AsyncResponder实例集。通过一些服务器端日志记录以及一些记录到SWF中的日志,我知道UrlLoader成功地执行并GET了crossdomain.xml文件,正确处理了它(即:如果我破坏它,我会得到一个安全错误),并且还成功完成了“load”请求(服务器发送数据)。下溢似乎发生在事件.COMPLETE监听/处理过程中(正如回溯所暗示的那样)。

mxmlc使用的版本为flex_sdk_4.5.0.20967

播放器示例(我尝试过几个)= 10.2.153.1


更新: 我的具体问题已解决... 但我仍然保留这个问题,因为我想知道如何通常调试这样的问题,而不仅仅是得到我的特定解决方案。

在我的代码中,我有以下应用程序定义:

<s:Application height="100%" width="100%"
                              xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx"
               initialize="InitData();">

请注意,代码附加到“initialize”事件。
InitData()和相关定义是/曾经是:
import classes.RpcServerProxy;
public var SP:RpcServerProxy;

public function InitData():void {
    SP = new RpcServerProxy("http://192.168.1.102:1234");
}

当我将InitData()调用改为在onCompletion事件上而不是initialize上时(感谢J_A_X!),问题完全消失了。似乎发生的事情是Event.COMPLETE事件处理程序(stack trace中的onComplete)正在使用全局SP对象。与发布(vs debug)编译有关的某些内容必须影响了SP变量初始化的启动时间。将处理程序后移至onCompletion事件可解决所有问题。
如上所述,我仍然想知道有哪些调试初始化问题的技巧/工具可用。

更新2:

applicationComplete 事件似乎比creationComplete 事件更适合放置应用程序初始化代码。请参见此博客文章进行一些解释,并参见Adobe Tech Evangelist的此视频(大约在4:25处)以获取有关简单的“应用程序启动”数据初始化的示例。


1
你能发布“complete”事件处理程序的代码吗? - Sean Fujiwara
@Sean Fujiwara:请看我上面的更新... - Russ
我和你一样遇到了同样的问题,但是在我的程序中出现在不同的位置。调整一些函数的调用顺序解决了这个问题。这真让人害怕。 - ADB
我刚刚遇到了这个问题。为什么这个问题在2016年还在发生?!:( - OMA
9个回答

12

我通过添加编译器参数-omit-trace-statements=false,解决了这个错误。


在我发现这是trace()问题后,我尝试了这个编译器选项。(omit-trace-statements) [链接](http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7a92.html) - Andrei
当在跟踪语句中使用getStackTrace()方法时,AIR似乎会窒息,而跟踪被省略。与其不在生产环境中省略跟踪(通过使用上述编译器参数),我认为最好在代码中使用全局“调试标志”,在开发时将其设置为true,在编译生产版本时将其设置为false。然后,每当您想要使用getStackTrace()时,都要添加对该标志的检查。 - OMA

4

堆栈下溢基本上意味着编译器出了问题。

如果您想知道它是如何出错的,可以使用 SWFWire Inspector查看事件处理程序的字节码。您还可以使用 SWFWire Debugger查看调用的方法,但在这种情况下,您已经知道发生了什么。

如果您发布有问题的swf文件,我可以给您更多信息。


3

肖恩是正确的,要调试它,您可以查看字节码,但我觉得这听起来并不吸引人。

根据我的经验和研究,通常是由于存在一个跟踪语句,在发布模式下被错误地编译出来,生成无效的字节码。因此,我会建议“调试”它,“查找您使用跟踪的位置。尝试在有问题的函数中将其全部注释掉,看看问题是否消失。”

在我的情况下,它是一个跟踪语句,作为catch块的第一行:

catch (e:TypeError) {
    trace(e.getStackTrace()); //This line is the problem
    throw new Error("Unexpected type encountered");
}

我在这里找到了另一个与此完全相同的问题:这里


那个链接已经过期了,我找不到替代的链接 -- 这里有一个来自wayback机器的备份:http://web.archive.org/web/20120101195442/http://www.slegg.net/ - jmoreno

2

对于寻找相同问题的人,我刚刚发现这是由于在switch语句的“default”情况下的跟踪语句所导致的。注释掉跟踪语句后,栈下溢问题得到解决。


2

这段代码只会在发布模式下(标志 -debug=false)导致堆栈下溢:

true && trace('123');

mxlmc flex sdk版本为4.5.0.20967,flashplayer版本为10.3.181.14(Linux)。

请检查您的代码是否存在类似的表达式。


2

当我从Flash Builder 4.5编译发布候选版时,这段代码给我带来了问题。

public function set configVO( value:PopupConfigVO ):void
        {trace("CHANGING")

通过在跟踪和花括号之间插入空格来解决问题。

public function set configVO( value:PopupConfigVO ):void
        { trace("CHANGING")

希望这能帮到您。

2

有趣...我从网上下载的一个基于Away3D的图形演示中遇到了这个错误。当时我是在Tamarin VM上运行它而不是在实际的Flash/AIR运行时上运行,所以我可以在“verifyFailed(kStackUnderflowError)”行上设置断点并查看发生了什么。

-Dverbose标志也有助于找到罪魁祸首:

typecheck MethodInfo-1480()
  outer-scope = [global]
                       [Object~ Object] {} ()
  0:pop
VERIFY FAILED: Error #1024: Stack underflow occurred.

使用 SWFInvestigator 查看 ABC 时,我发现了以下内容:

var function(Object):void   /* disp_id=0 method_id=1480 nameIndex = 0 */
{
   // local_count=2 max_scope=0 max_stack=0 code_len=2
   // method position=52968 code position=155063
   0      pop               
   1      returnvoid        
}

因此,这里存在一个明显的问题,即“跟踪”已被移除,但编译器却放置了一个“pop”:我认为这并不需要,因为通过“callpropvoid”应该可以调用跟踪调用?不知道为什么这在AIR / Flash上不会失败。
总之,对我来说看起来像是ASC编译器的问题,也就是说,可能有一个ActionScript3编译器存在故障 - 因此迄今为止已经提到的工作区。

1

这很简单,与括号前后的空格、跟踪命令或其他任何内容无关:只有一个非常简单的事情:

不要循环空值!

也就是说,在开发过程中,我们有时会//注释掉一些代码行,但当这导致出现空值循环时,就需要注意了。

 for (...) { 
             // skip for now
         }

编译器得到的信息是:
      for(...){}

我的好朋友,这是编译器不喜欢的事情!

所以,不要有空循环,你就可以继续前进了...

祝你好运,
P.


这正是我的问题。首先要查找它;很容易发现和修复。在我的情况下,它是for (var key:String in foo),堆栈跟踪指向不同位置。 - Olin Kirkland

0

我曾经遇到过完全相同的问题,但在我的情况下,问题的原因是一个跟踪语句出现在编译器不希望找到它的地方,就在类开始处的包声明之后:

package utils 
{

trace ("trace something here");

这就是为什么在调试模式下编译可以解决问题的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接