Как отладить ошибку стека стека во время выполнения?
Я действительно пытаюсь решить проблему стека, которую я получаю. След, который я получаю во время выполнения:
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, а затем вызывает набор экземпляров AsyncResponder, связанных с AsyncToken. С некоторыми протоколами на стороне сервера, а также с некоторыми протоколами, взломанными в swf, я знаю, что UrlLoader успешно выполняет и GET'ing файл crossdomain.xml, правильно обрабатывает его (то есть: если я его обману, я получаю защиту ошибка), а также успешно завершает запрос "load" (сервер отправляет данные). Как представляется, процесс underflow происходит в процессе прослушивания/обработки Event.COMPLETE(как, конечно, подразумевается также трассировка).
mxmlc used = from 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() и соответствующие defintions являются/были:
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 Евангелист за примером простой инициализации данных "запуска приложения".
Ответы
Ответ 1
Недостаток стека в основном означает, что компилятор испорчен.
Вы можете использовать SWFWire Inspector, чтобы посмотреть на байт-код обработчика событий, если вы хотите точно знать, как он перепутался. Вы также можете использовать SWFWire Debugger, чтобы узнать, какие методы были вызваны, но в этом случае вы уже знали, где это происходит.
Если вы опубликуете сломанный swf, я могу дать вам больше информации.
Ответ 2
Я избавился от этой ошибки, добавив аргумент компилятора:
-omit-следовая-выписка = ложь
Ответ 3
Шон прав, что для его отладки вы можете посмотреть на байтовый код, но это не звучит привлекательно для меня.
Основываясь на моем опыте и исследованиях, это часто связано с наличием оператора трассировки, который некорректно компилируется в режиме деблокирования и генерирует неверный код байта. Итак, я бы сказал "отлаживать" его: "Ищите места, где вы используете трассировку. Попробуйте прокомментировать их в функции оскорбления и посмотрите, не пропадет ли проблема".
В моем случае это был оператор trace как первая строка блока catch:
catch (e:TypeError) {
trace(e.getStackTrace()); //This line is the problem
throw new Error("Unexpected type encountered");
}
Я нашел кого-то другого с этой точной проблемой здесь.
Ответ 4
Этот код также приводит к переполнению стека только в режиме деблокирования (флаг -debug = false):
true && trace('123');
mxlmc flex sdk версия 4.5.0.20967, версия flashplayer 10.3.181.14 (linux).
Проверьте код для аналогичных выражений.
Ответ 5
Этот код вызвал у меня проблемы, когда я скомпилировал кандидат на выпуск из Flash Builder 4.5
public function set configVO( value:PopupConfigVO ):void
{trace("CHANGING")
Решено путем вставки пробела между трассировкой и фигурной скобкой
public function set configVO( value:PopupConfigVO ):void
{ trace("CHANGING")
Надеюсь, что это поможет.
Ответ 6
Для людей, которые ищут одну и ту же проблему, я просто получил это из-за оператора трассировки в случае "по умолчанию" оператора switch. Прокомментировал трассировку, стекирование недополучено.
Ответ 7
Интересно... Я получал эту ошибку со SWF, который я снял с веб-страницы, демо-версию 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.
И, глядя на 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 была ошибка с этим - следовательно, обходные решения, которые были упомянуты до сих пор.
Ответ 8
У меня была такая же проблема, но в моем случае причиной проблемы был оператор trace в месте, где компилятор не ожидал его найти сразу после объявления пакета в начале класса:
package utils
{
trace ("trace something here");
И поэтому компиляция в режиме отладки устраняет проблему.
Ответ 9
Это довольно просто, и он не имеет ничего общего с пробелами до или после скобок, команд трассировки или что-то еще: это всего лишь 1 очень простая вещь:
НЕ ПОТЕРЯЙТЕ ПУСТОЙ!
Значение, при разработке, мы все//иногда комментируем некоторые строки, и когда это приводит к
for (...) {
// skip for now
}
компилятор получает:
for(...){}
и что мои хорошие друзья, это то, что компилятор не любит!
Итак, NO пустых циклов, и вы снова на своем пути...
Счастливая охота,
Р.