Размотка глубоких штабелей

В первую очередь, это точно про C, никаких решений на C ++ не требуется.

Цель: возврат к вызывающей функции (A) за пределами нескольких фреймов стека.

У меня есть несколько решений, но ни одно из них не кажется лучшим вариантом.

Самый простой в смысле реализации - longjmp / setjmp, но я не уверен, уничтожает ли он автоматические переменные, потому что, как указано в wiki, нормальное разматывание стека не происходит, если выполняется longjmp.

Вот краткое описание потока программы: функция A вызывает функцию file processing, что приводит к множеству внутренних и рекурсивных вызовов. В какой-то момент программа чтения файлов встречает EOF, поэтому работа file processing выполнена, и управление должно быть передано функции A.

Сравнивая каждый прочитанный символ с EOF или '\ 0'? Нет, спасибо. UPD: я могу избежать динамического выделения памяти в цепочке вызовов между setjmp и longjmp.

Не будучи уверенным в автоматических переменных, я не знаю, что произойдет при последовательных вызовах file processing (файлов больше 1).

So:

1) Что насчет "без раскрутки стека" от longjmp? Насколько опасно, что у меня есть все держатели данных (указатели).

2) Другие изящные и эффективные способы вернуться к A фрейму?


person Iskander Sharipov    schedule 02.01.2015    source источник
comment
Вам придется избегать сохранения состояния, которое требует очистки в стеке, и регистрировать функции очистки таким образом, чтобы цель вашего longjmp могла их вызывать (мало чем отличается от того, что делает C ++ во время обработки исключений ;-)   -  person thebjorn    schedule 02.01.2015
comment
Итак, в основном вам нужны исключения в C, потому что вы не хотите выполнять проверку ошибок на каждом уровне. В этом случае разматывание стека - не единственная проблема. Вам нужно быть очень осторожным с динамически выделяемой памятью и указателями, которые могут потеряться по пути.   -  person SirDarius    schedule 02.01.2015
comment
Как указывает @thebjorn, вам, вероятно, потребуется реализовать некоторую структуру для очистки, особенно если вы не открыли все файлы до setjmp() или (например) не выделяли память во время выполнения. Если это сложно, как вы говорите, вы можете обнаружить, что регистрация и отмена регистрации этих очисток не проще, чем более традиционная модель. Нередко можно найти программы на C, которые на 50% обрабатывают ошибки, особенно при работе с файловым вводом-выводом.   -  person Persixty    schedule 02.01.2015
comment
Будьте осторожны при использовании рекурсии для данных, размер которых вы заранее не знаете. В некоторых входных файлах может возникнуть переполнение стека.   -  person jmajnert    schedule 02.01.2015


Ответы (1)


Я не знаю, что вы где-то читали, но setjmp/longjmp - это именно тот инструмент, который предусмотрен для этой задачи.

longjmp восстанавливает «стек» точно (в некотором роде), как это было при вызове setjmp, все изменения в «стеке», которые были сделаны между ними, теряются, включая все auto переменные, которые были определены. Это восстановление стека является прямым перебором, в C нет концепции деструкторов, и это, возможно, подразумевается под «без раскрутки стека».

Я заключил «стек» в кавычки, так как это не тот термин, который применяется в стандарте C, он говорит только о состоянии и позволяет организовать его так, как это удобно для реализации.

Теперь единственная информация, которую вы можете сохранить за время между setjmp и longjmp:

  • значение, которое вы передаете longjmp
  • значение измененных volatile объектов, которые вы определили до setjmp

Итак, в ветке, из которой вы вернулись из longjmp, вы должны использовать эту (и только эту) информацию для устранения беспорядка: закрыть файлы, free объекты, которые вы malloced и т. Д.

person Jens Gustedt    schedule 02.01.2015
comment
Спасибо за разъяснения. Но даже если это инструмент, предусмотренный для этой задачи, довольно сложно начать использовать его после того, как многие люди сочтут его опасным. - person Iskander Sharipov; 02.01.2015
comment
@IskanderSharipov, конечно, никто не говорил, что будет легко :) Первый вопрос, который стоит задать себе, - стоит ли оно того. Всплывающее окно из рекурсии после долгой обработки файла не должно оказывать заметного влияния на время обработки. Что касается всего этого, определите настоящие узкие места вашей программы, прежде чем приступать к такой тонкой оптимизации. - person Jens Gustedt; 02.01.2015