LINUX.ORG.RU

Segmentation fault при компиляции с оптимизацией


0

0

Здравствуйте!

У меня сложилась довольно забавная ситуация:

Программа выдаёт segmentation fault если её скомпилить с флагами оптимизации,
а при -O0 всё нормально.

Долгое отслеживание вставкой printf'ов показало, что падение происходит при
выходе из функции (т.е. printf перед return'ом проходит, а сразу после вызова этой
функции -- нет).

valgrind показывает (при -O0, иначе не доходит) несколько "Conditional jump
or move depends on uninitialised value(s)", но уже ПОСЛЕ этого фрагмента.
Кстати особенно в одном месте я абсолютно уверен, что переменная всё же
инициализируется, потому что код выглядит так:

    int res=0;

    dizcrossflags_t crossed_flags;
    dizcrossflags_t av_crossed_flags;
    do
    {
      ....
    }
    while (queue);
    if (res) res=DIZ_EVENTHANDLER_ERROR;

valgrind утвеждает что в последней строке этого фрагмента имеет место
использование неинициализированной переменной. Но res очевидно всё же
инициализирован выше, а DIZ_EVENTHANDLER_ERROR, это макрос -- число.

Вообще valgrind также показывает ну, очень много "Conditional jump or move
depends on uninitialised value(s)" в модуле /usr/lib/libGLcore.so.1.0.7174, т.е.
драйверах OpenGL от NVidia. Как бы его заставить игнорировать их..

Так вот, неужели я смог-таки написать правильный код, который
не компилится gcc правильно с оптимизацией?
★★★★★

Совершенно очевидно, что ты где-то срёшь в память. Или пишешь за пределы выделенной памяти, и, в зависимости от оптимизации, либо ничего не портишь, либо гадишь в какой либо нужный указатель, либо используешь вообще неинициализированный указатель, либо пишешь в уже освобождённую память. Все симптомы очевидны, и не надейся, что ты gcc на глюке подловил.

Вывод простой - рано тебе ещё на Си писать.

JavaHarlal
()
Ответ на: комментарий от JavaHarlal

> Совершенно очевидно, что ты где-то срёшь в память.

Однако, подобная ситуация уже возникала, но тогда я valgrind'ом нашёл ошибку, а сейчас неужели он её не видит...

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от unDEFER

Прав JavaHarlal - у меня такое было когда в память гадил. А то, что это происходит при выходе из функции, дык это где-то в диструкторе какого-то автоматического объекта происходит, imho.

ebersen
()

printf ХА хА ХА

Да ту чувак отстал от жизни, такие ошибки обычно при помощи GDB ловят.

aton
()
Ответ на: комментарий от ebersen

Да, у меня тоже такое ранее было, но я ещё раз говорю -- тогда я с помощью valgrind легко нашёл ошибку. А сейчас её не видно. Кстати только что исбавился от одного "Use of uninitialised value of size 4". Не помогло. А кто-нибудь может что-нибудь сказать по выше приведённому коду? Кажется это последняя ошибка которую видит valgrind (остальные все в GLcore).

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от aton

> Да ту чувак отстал от жизни, такие ошибки обычно при помощи GDB ловят.

Обычно, но не в этом случае -- из-за оптимизации он не может определить модуль в котором произошла ошибка -- одни "????"

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от aton

> гониш, оптимизация ни как не влияет на отладочные символы

Как знаешь, но практика показывает что ни один отладчик (что gdb, что valgrind) при оптимизации уже не может точно определить к какой строке относится тот или иной объектный код.

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от unDEFER

> Возможно, но до сих пор работало...

Ты что, так только всё и оцениваешь? До сих пор работало, блин? Как тот альпинист, летящий в пропасть - "ну, пока всё в порядке"...

Полную гарантию тебе даст только:

- отсутствие арифметики указателей

- поддержка массивов и строк на уровне языка (проверка на переполнения)

Никакая библиотека и никакой дебаггер эти глюки самого языка не исправят. И если ты не знаешь досконально все слабые стороны Си, не знаешь, как защищаться от проблем такого рода, то тебе просто нельзя на Си писать. Понятно?

Baraban
()
Ответ на: комментарий от Baraban

> И если ты не знаешь досконально все слабые стороны Си, не знаешь, как защищаться
> от проблем такого рода, то тебе просто нельзя на Си писать. Понятно?

Успокойся -- практика, практика и ещё раз практика, только так можно реально узнать как что может быть, а что нет.
Несомненно теория хороша, но без практики реального знания никогда не будет -- будет только "я слышал, что", "я читал, что", но не "я знаю, что". Вот так.

Можно сказать и так:
теория -- необходимое условие знания, а практика -- достаточное.

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от Baraban

> Нельзя начинать, как ты, браться за практику без теории. Тренируйся пока на Java...

Ну, ну.. и чему я натренируюсь, когда за мной автоматически будут мусор подчищать?
Как раз что бы тренироваться убирать за собой мусор вручную, надо его убирать вручную!

Кстати ещё раз о моём не верном суждении по поводу valgrind. Я говорю до сих пор я не видел, чтобы он врал _на_моей_машине_, если сейчас я всё же найду ошибку, значит я уже буду _знать_ что это действительно бывает, что он чего-то не замечает, а до этого разумеется я предполагал, что в теории он может ошибаться.

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от unDEFER

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

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

Baraban
()
Ответ на: комментарий от Baraban

> Изучи теорию - чтоб не предполагать, а знать. Ошибаться он может и должен, у него
> теоретически нет возможностей найти ВСЕ ошибки.

Все, нет, а вот утечек и неправильных использований указателей, по-моему, вполне возможно.
А что ты мне предложишь в качестве теоритического пособия: код ядра, код valgrind или документацию vaglrind?

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от Baraban

И ещё раз повторюсь "знать теорию" и "знать" -- это разные вещи.
( Кстати, в теории ведь это может быть и ошибкой gcc :-)) )

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от unDEFER

> Все, нет, а вот утечек и неправильных использований указателей, по-моему, вполне возможно.

Нет. Нельзя.

Например, он не отследит все случаи обращения к уже освобождённой памяти.

Теория - ну, тут, например:

http://manju.cs.berkeley.edu/ccured/

Baraban
()

Выведи значение укозателя возврата при входе в глякавую функцию и сразу перед выходом из её. Если различаются, а я полагаю что будут, налицо порчя стека.

bugmaker ★★★★☆
()
Ответ на: комментарий от Baraban

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

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от bugmaker

> Выведи значение укозателя возврата при входе в глякавую функцию и сразу перед выходом из её.

Простите.. А как это сделать?

unDEFER ★★★★★
() автор топика

Что ж, всем спасибо.
Проблема нашлась -- звёздочку я забыл :-)
То как я решал, конечно, эту проблему это смешно, но я поступил так как подсказывала мне природная лень:
так как в принципе без оптимизации всё работало, я решил не заморачиваться, а просто писать нужный мне код дальше -- ожидания меня не обманули -- сразу как только я завершил весь этот фрагмент, ошибка тут же всплыла, и с помощью gdb я уже узнал где берётся корень.

Конечно, тут возникал вопрос -- "и как вообще оно работало с этим?".
Ответ однако прост -- модуль в котором была допущена ошибка можно сказать не использовался в программе -- т.е. в нём происходила инициализация (ошибочно) некоторых данных, но затем они не использовались. Если бы я включил этот модуль (а выключен он временно), то ошибка тут же бы всплыла.

unDEFER ★★★★★
() автор топика
Ответ на: комментарий от unDEFER

Имхо начинать надо было с gdb, а не с valgrind. И себе бы жизнь упростил и флейм бы не развёлся.

jek_
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.