Flex выдает фатальную внутреннюю ошибку сканера - пропущен конец буфера

Я пытаюсь использовать flex против буфера, который постоянно заполняется и пополняется.

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

В psuedo в моей основной программе это выглядит примерно так:

while(forever)
{
-fill buffer buf-
buf[length+1] = '\0';
buf[length+2] = '\0';
yy_scan_bytes(&buf, length+2);
yylex();
}

где несколько потоков выполняют этот цикл, и все они владеют своей копией buf.

У меня есть правило в моем файле lex, которое выглядит так:

<<EOF>> {yyterminate(); yy_delete_buffer(YY_CURRENT_BUFFER);}

в попытке очистки после запуска буфера.

Я не уверен, что делаю это правильно, так как это моя первая попытка использовать гибкий сканер в сочетании с другой программой. Было бы лучше, если бы я выполнял всю обработку буфера из flex и связывал его с объявлением extern в моей основной программе?

Спасибо


person Derek    schedule 18.12.2012    source источник


Ответы (1)


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

Вам нужно использовать %option reentrant для создания реентерабельного сканера, а затем создать отдельный yyscan_t для каждого используемого потока, который вы инициализируете с помощью yylex_init, а затем передаете в качестве дополнительного аргумента как yylex, так и yy_scan_bytes.

Кроме того, yyterminate выполняет немедленный возврат из сканера, поэтому ваш вызов yy_delete_buffer никогда не выполняется. Вам нужно вызвать его после возврата сканера:

yyscan_t local;
yylex_init(&local);
while(forever)
{
    -fill buffer buf-
    buf[length+1] = '\0';
    buf[length+2] = '\0';
    YY_BUUFER_STATE bs = yy_scan_bytes(&buf, length+2, local);
    yylex(local);
    yy_delete_buffer(bs, local);
}
person Chris Dodd    schedule 18.12.2012
comment
Играя с этим, есть ли смысл для меня создавать функцию в сканере, которая берет мой буфер и выполняет yylex_init и т. д. в этой функции? Это единственный способ получить доступ к yyscan_t и другим переменным, которые я не мог получить в своей основной программе? - person Derek; 19.12.2012
comment
@Derek: поместите весь этот код в 3-й раздел файла .l, чтобы он мог получить доступ ко всем типам и объявлениям, определенным flex. - person Chris Dodd; 19.12.2012
comment
Спасибо за ваши ответы. Я начинаю пытаться исправить это, и я получаю нераспознанную опцию в опции. у меня гибкая версия 2.5.4 (pcbsd), эта опция была введена позже? - person Derek; 19.12.2012
comment
Обновление действительно решило проблему повторного входа. просто чтобы уточнить для кого-либо еще - buf, который вы использовали как YY_BUFFER_STATE, имеет конфликт имен с буфером, в котором хранятся данные в вашем примере. - person Derek; 19.12.2012
comment
Я приму этот ответ, потому что он ответил на суть того, что я пытался сделать, но теперь у меня есть дополнительный вопрос: stackoverflow.com/questions/13957454/ - person Derek; 19.12.2012