Как отладить ошибку опустошения стека во время выполнения? - PullRequest
12 голосов
/ 07 июня 2011

Я действительно изо всех сил пытаюсь разрешить переполнение стека, которое я получаю. Трассировка, которую я получаю во время выполнения:

VerifyError: Error #1024: Stack underflow occurred.

at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/onComplete()

Это особенно сложно для отладки, потому что когда я работаю в режиме отладки, это вообще не происходит. Это происходит только при компиляции как релиз.

У кого-нибудь есть какие-либо советы по отладке Stack Underflow? Есть ясное объяснение того, что это значит для Flash?

В случае, если это помогает, эта ошибка возникает, когда я нажимаю кнопку, чей обработчик выполняет вызов RPC, который использует URLLoader, AsyncToken, а затем вызывает набор экземпляров AsyncResponder, связанных с AsyncToken. С некоторой регистрацией на стороне сервера, а также с регистрацией, взломанной в swf, я знаю, что UrlLoader успешно делает и GET'ing файл crossdomain.xml корректно обрабатывает его (то есть: если я уничтожаю его, я получаю защиту ошибка), а также успешно завершает запрос «загрузка» (сервер отправляет данные). Похоже, что процесс переполнения происходит в процессе прослушивания / обработки Event.COMPLETE (что, конечно, также подразумевается при трассировке).

mxmlc used = из 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 () и соответствующие определения: / 1027 *

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 (onComplete в трассировке стека) использовал глобальный объект SP. Что-то в компиляции release (vs debug) должно было повлиять на время запуска инициализации переменной SP. Перемещение обработчика позже к событию onCompletion решило все проблемы.

Как уже было сказано выше, я все же хотел бы знать, какие хитрости / инструменты доступны для устранения подобных проблем инициализации.


ОБНОВЛЕНИЕ 2:

applicationComplete представляется даже лучшим событием, чем creationComplete для добавления кода инициализации приложения. См. эту запись в блоге для некоторых пояснений и это видео (около 4:25) от Adobe Tech Evangelist для примера простой инициализации данных "запуска приложения".

Ответы [ 9 ]

12 голосов
/ 13 сентября 2012

Я избавился от этой ошибки, добавив аргумент компилятора:
-omit-следовой заявления = ложь

4 голосов
/ 08 июня 2011

Недостаточность стека в основном означает, что компилятор испортился.

Вы можете использовать SWFWire Inspector , чтобы посмотреть байт-код обработчика события, если вы хотите точно знать, как он испортился.Вы также можете использовать SWFWire Debugger , чтобы увидеть, какие методы были вызваны, но в этом случае вы уже знали, где это происходит.

Если вы опубликуете сломанный SWF, я могу дать вам большеИнформация.

3 голосов
/ 13 февраля 2012

Шон прав, что для его отладки вы можете посмотреть байт-код, но мне это не показалось привлекательным.

Судя по моему опыту и исследованиям, это часто связано с наличием оператора трассировки, который неправильно компилируется в режиме выпуска и генерирует недопустимый байт-код.Поэтому я бы сказал «отладить» его: «Найдите места, где вы используете трассировку. Попробуйте закомментировать их все в функции-нарушителе и посмотрите, исчезнет ли проблема».

В моем случае этобыла инструкция трассировки в качестве первой строки блока catch:

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

Я нашел кого-то еще с этой проблемой здесь .

2 голосов
/ 03 мая 2013

Интересно ... Я получал эту ошибку с SWF, который я вытащил из Интернета, демонстрацию графики на основе Away3D. В то время, когда я выполнял это на виртуальной машине Tamarin, а не на реальных средах выполнения Flash / AIR, можно установить точку останова в строке verifyFailed (kStackUnderflowError) и посмотреть, что происходит.

Флаг -Dverbose также помог найти виновника:

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

И, глядя на ABC с помощью SWFInvestigator, я нашел это:

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        
}

Таким образом, существует очевидная проблема, когда «трассировка» была удалена, но компилятор добавил туда «поп»: я бы не подумал, что это необходимо, поскольку вызов трассировки, вероятно, должен был быть сделан с помощью «callpropvoid». «

Я не знаю, почему это не сработает в AIR / Flash.

В любом случае: мне кажется, что проблема с компилятором ASC, т. Е., Возможно, в этом был один из компиляторов ActionScript3 - отсюда и обходные пути, о которых уже упоминалось.

2 голосов
/ 07 сентября 2012

Для людей, ищущих ту же проблему, я просто получил это из-за оператора трассировки в случае «по умолчанию» оператора switch. Закомментирована трассировка, устранена потеря значения стека.

2 голосов
/ 24 января 2012

Этот код вызвал у меня проблемы при компиляции кандидата на выпуск из Flash Builder 4.5

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

Решается путем вставки пробела между трассировкой и фигурной скобкой

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

Надеюсь, этопомогает.

2 голосов
/ 04 августа 2011

Этот код также приводит к переполнению стека только в режиме выпуска (флаг -debug = false):

true && trace('123');

mxlmc flex sdk версия 4.5.0.20967, версия flashplayer 10.3.181.14 (linux).

Проверьте ваш код на похожие выражения.

0 голосов
/ 26 февраля 2014

Это довольно просто, и оно не имеет ничего общего с пробелами до или после скобок, команд трассировки или чего-либо еще: это просто 1 действительно простая вещь:

НЕ ЗАПУСКАЙТЕ ПУСТОЙ!

То есть при разработке мы все // иногда комментируем некоторые строки, и когда это приводит к

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

, компилятор получает:

      for(...){}

и что мои хорошие друзья,это то, что компилятору не нравится!

так что, НИКАКИХ пустых циклов, и вы снова в пути ...

Удачной охоты, P.

0 голосов
/ 02 июля 2013

У меня была точно такая же проблема, но в моем случае причиной проблемы был оператор трассировки в месте, где компилятор не ожидал его найти, сразу после объявления пакета в начале класса:

package utils 
{

trace ("trace something here");

И именно поэтому компиляция в режиме отладки устранила проблему.

...