Stack underflow ошибка печати

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

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

VerifyError: Error #1024: Stack underflow occurred.

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

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

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

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

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

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


обновление 2:

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

9 ответов


Stack underflow в основном означает, что компилятор испортился.

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

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


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


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

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

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

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

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


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

true && trace('123');

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

проверьте код на наличие подобных выражений.


этот код вызвал у меня проблемы, когда я скомпилировал кандидата на выпуск из flash builder 4.5

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

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

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

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


для людей, ищущих ту же проблему, я только что получил это, вызванное оператором трассировки в случае «по умолчанию» оператора switch. Прокомментировал трассировку, stack underflow разрешен.


интересные… Я получал эту ошибку с SWF, который я вытащил из интернета, графическую демонстрацию на основе Away3D. В то время я запускал это на VM 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        
}

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

вполне почему это не терпит неудачу на AIR / Flash, я не знаю..

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


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

package utils 
{

trace ("trace something here");

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


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

НЕ ЦИКЛ ПУСТОЙ!

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

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

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

      for(...){}

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

Итак, никаких пустых петель и ты снова в пути…

счастливой охоты,
П.


Я написал фрагмент кода Java для отправки сценариев postscript в формате PDF на сетевой принтер через Socket.

Файлы были напечатаны в идеальной форме, но каждое задание сопровождается одной или двумя дополнительными страницами с такими текстами, как ps: stack underflow или error undefined offending command.

Сначала я подумал, что с процессом PDF2PS что-то не так, поэтому попробовал 2 файла PS из этого Файлы PS. Но проблема все еще существует.

Я также проверил файлы ps с помощью GhostView. Теперь я думаю, что с кодом что-то не так. Код не вызывает исключений.

Принтер Toshiba e-studion 5005AC поддерживает PS3 и PCL6.

    File file = new File("/path/to/my.ps");

    Socket socket = null;
    DataOutputStream out = null;
    FileInputStream inputStream = null;
    try {
        socket = new Socket(printerIP, printerPort);
        out = new DataOutputStream(socket.getOutputStream());
        DataInputStream input = new DataInputStream(socket.getInputStream());
        inputStream = new FileInputStream(file);
        byte[] buffer = new byte[8000];

        while (inputStream.read(buffer) != -1) {
            out.write(buffer);

        }

        out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

1 ответ

Лучший ответ

Вы записываете весь буфер в выходной поток независимо от того, сколько фактического содержимого там. Это означает, что когда вы пишете буфер в последний раз, в конце буфера, скорее всего, будет куча содержимого из предыдущей итерации.

Примере

Например представьте, что у вас есть следующий файл и вы используете буфер размером 10:

 1234567890ABCDEF

После первого вызова inputStream.read() он вернет 10, и в буфере у вас будет:

 1234567890

После второго вызова inputStream.read() он вернет 6, и в буфере у вас будет:

 ABCDEF7890

После третьего вызова inputStream.read() он вернет -1, и вы перестанете читать.

В конце концов, сокет принтера получит эти данные:

1234567890ABCDEF7890

Здесь последний 7890 — это дополнительный бит, который принтер не понимает, но он может успешно интерпретировать первый 1234567890ABCDEF.

Fix

Вы должны учитывать длину, возвращаемую inputStream.read():

        byte[] buffer = new byte[8000];
        for (int length; (length = inputStream.read(buffer)) != -1; ){
            out.write(buffer, 0, length);
        }

Также рассмотрите возможность использования try-with-resources, чтобы избежать проблем с незамкнутые потоки.


1

Devstr
13 Фев 2018 в 19:57

Перевод публикуется с сокращениями, автор оригинальной статьи Megan Kaczanowski.

C, C++ и Objective-C являются ключевыми языками, имеющими уязвимости переполнения буфера, поскольку они работают с памятью более непосредственно чем многие интерпретируемые языки.

Даже если код написан на
«безопасном» языке (например, на Python), если используются любые
написанные на C, C++ или Objective C библиотеки, он все равно может быть уязвим для
переполнения буфера.

Выделение памяти

Чтобы понять механизм возникновения переполнения буфера, нужно немного разобраться с выделением памяти в программы. В написанном на языке С приложении можно выделить память в стеке во время компиляции или в куче
во время выполнения.

  • Объявление переменной в стеке: int numberPoints = 10.
  • Объявление переменной в куче: int* ptr = malloc (10 * sizeof(int)).

Переполнение буфера может
происходить в стеке (переполнение стека) или в куче (переполнение кучи). Как
правило, переполнение стека встречается чаще. Он содержит
последовательность вложенных функций: каждая из них возвращает адрес
вызывающей функции, к которой нужно вернуться после завершения работы.
Этот возвращаемый адрес может быть заменен инструкцией для выполнения фрагмента
вредоносного кода.

Поскольку куча реже хранит возвращаемые адреса, гораздо сложнее (хотя в ряде случаев это возможно) запустить эксплойт. Память в куче обычно содержит данные программы и динамически
выделяется по мере ее выполнения. Это означает, что при переполнении
кучи, скорее всего, перезапишется указатель функции – такой путь более сложен и менее
эффективен чем переполнение стека.

Поскольку переполнение
стека является наиболее часто используемым типом переполнения буфера, кратко
рассмотрим, как именно они работают.

Переполнение стека

Эксплуатация уязвимости происходит внутри процесса, при этом каждый процесс имеет свой
собственный стек. Когда он выполняет основную функцию, то находит как новые
локальные переменные (которые будут «запушены» в начало стека), так и вызовы других
функций (которые создадут новый «стекфрейм»).

Схема стека:

❓ Что такое переполнение буфера и как с ним бороться

Что такое stackframe?

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

Чтобы отслеживать этот
процесс, компьютер хранит в памяти несколько указателей:

  • Stack Pointer: указывает на топ стека вызовов процесса (или на последний помещенный в стек элемент).
  • Instruction Pointer: указывает на адрес следующей инструкции процессора, которая будет выполнена.
  • Base Pointer (BP): (также известный как указатель кадра) указывает на основание текущего кадра стека. Он остается постоянным до тех пор, пока программа выполняет текущий стекфрейм (хотя указатель стека может измениться).

Для примера рассмотрим
следующий код:

        int main() {
    int j = firstFunction(5);
    return 0;
}
    
int firstFunction(int z) {
    int x = 1 + z;
    return x;
}
    

Стек вызовов будет
выглядеть следующим образом, сразу после вызова firstFunction и выполнения
оператора int x = 1+z:

❓ Что такое переполнение буфера и как с ним бороться

Здесь main вызывает
firstFunction (которая в данный момент выполняется), поэтому она находится в
верхней части стека вызовов. Возвращаемый адрес – это адрес в памяти,
относящийся к функции, которая его вызвала (он удерживается указателем
инструкции при создании стекфрейма). Локальные переменные, которые все еще
находятся в области видимости, также находятся в стеке вызовов. Когда они
выполняются и выходят за пределы области действия, они удаляются из верха
стека.

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

Пример уязвимости переполнения
буфера:

        int main() {
    bufferOverflow();
 }
 
 bufferOverflow() {
    char textLine[10];
    printf("Enter your line of text: ");
    gets(textLine);
    printf("You entered: ", textLine);
    return 0;
 }
    

Этот простой код считывает произвольное количество данных (gets будет считывать до конца файла
или символа новой строки). Рассмотрев его, можно понять опасность. Если пользователь вводит больше данных, чем помещается в
выделенную
для переменной область, введенная строка перезапишет следующие
ячейки памяти в стеке вызовов. Если она достаточно длинная, перезапишется даже обратный адрес вызывающей функции.

Как компьютер отреагирует на это, зависит от реализации стеков и выделения памяти в конкретной системе. Реакция на переполнение буфера может быть совершенно непредсказуемой, начиная от сбоев программы и заканчивая выполнением вредоносного кода.

Почему происходит переполнение буфера?

Причина, по которой переполнение буфера стало такой серьезной проблемой, заключается в отсутствии проверки границ во многих функции управления памятью в C и C++. Хотя этот процесс сейчас довольно хорошо известен, он также очень часто эксплуатируется (например, зловред WannaCry использовал переполнение буфера).

Переполнение буфера чаще всего происходит, когда код зависит от внешних входных данных и слишком сложен для программиста, чтобы понять его поведение или когда он имеет зависимости за пределами прямой видимости кода.

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

Как уменьшить влияние переполнения
буфера:

  • Используйте интерпретируемый язык, который не подвержен этим проблемам.
  • Избегайте использования функций, которые не выполняют проверку буфера (например, в C вместо функции gets() используйте функцию fgets()).
  • Применяйте компиляторы, которые помогают определить небезопасные функции или найти ошибки.
  • Используйте canaries, которые могут помочь предотвратить переполнение буфера. Они вставляются перед обратным адресом в стеке и проверяются перед обращением к нему. Если программа обнаружит изменение значения canary, она прервет процесс, не позволив злоумышленнику пробиться. Значение canary является либо случайным (поэтому злоумышленнику очень трудно его угадать), либо строкой, которую по техническим причинам невозможно перезаписать.
  • Переставляйте локальные переменных таким образом, чтобы скалярные (отдельные объекты данных фиксированного размера) были выше переменных массива, содержащих несколько значений. Это означает, что если переменные массива переполняются, они не будут влиять на скалярные переменные. Этот метод в сочетании с canary-значениями очень помогает.
  • Сделайте стек неисполняемым, установив бит NX (No-eXecute), чтобы злоумышленник не вставлял шелл-код непосредственно в стек и не выполнял его там. Это неидеальное решение, так как даже неисполняемые стеки могут стать жертвами атак переполнения буфера, вроде return-to-libc. Эта атака происходит, когда обратный адрес стекового фрейма заменяется адресом библиотеки, уже находящейся в адресном пространстве процесса. К тому же не все процессоры позволяют установить бит NX.
  • ASLR (рандомизация расположения адресного пространства) может служить общей защитой, а также специфической защитой от атак return-to-libc. Это означает, что всякий раз, когда файл библиотеки или другая функция вызывается запущенным процессом, ее адрес сдвигается на случайное число. Это делает практически невозможным связать фиксированный адрес памяти процесса с функциями, из чего следует, что злоумышленнику может быть трудно узнать, откуда вызывать определенные функции. ASLR включен по умолчанию во многих версиях Linux, OS X и Android.

Stack Underflow

Такая уязвимость возникает, когда две части программы по-разному обрабатывают один и
тот же блок памяти. Например, если вы выделите массив размером X, но заполните
его массивом размером x < X, а затем попытаетесь извлечь все X байтов, скорее
всего вы получите «грязные» данные для X – x байтов.

Вы, возможно,
извлекли данные, которые остались после использования этой области памяти ранее. В лучшем случае это мусор, который ничего не значит, а в худшем – конфиденциальные данные, которыми может злоупотребить злоумышленник.

Заключение

Рассмотренная уязвимость
является очень серьезной угрозой стабильной работе любого продукта.
Необходимо приложить все усилия и проверить ваши проекты на ее наличие, т. к. последствия могут быть весьма плачевными (уже упоминался
Ransome) и болезненными. Используйте советы из статьи и вы уменьшите вероятность успешного проникновения
злоумышленников в ваш код. Удачи в обучении!

Дополнительные материалы:

  • Алгоритмы в C++: запросы к статическим массивам
  • ТОП-10 трюков на C++, которые облегчат вам жизнь
  • Сайт на C++ своими руками с помощью библиотеки cgicc
  • 5 шагов для создания простой формы входа на C#
  • 10 самых популярных алгоритмов сортировки на C#

Источники

  • https://www.freecodecamp.org/news/buffer-overflow-attacks/

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

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 Евангелист за примером простой инициализации данных «запуска приложения».

4b9b3361

Ответ 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 пустых циклов, и вы снова на своем пути…

Счастливая охота,
Р.

Понравилась статья? Поделить с друзьями:
  • St link usb communication error
  • Stack trace сталкер call of chernobyl как исправить
  • St link keil internal command error
  • Stack overflow ошибка delphi
  • Sssd tsig error with server tsig verify failure