Здравствуйте!
У меня сложилась довольно забавная ситуация:
Программа выдаёт 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 - у меня такое было когда в память гадил. А то, что это происходит при выходе из функции, дык это где-то в диструкторе какого-то автоматического объекта происходит, imho.
Да, у меня тоже такое ранее было, но я ещё раз говорю -- тогда я с помощью valgrind легко нашёл ошибку. А сейчас её не видно. Кстати только что исбавился от одного "Use of uninitialised value of size 4". Не помогло. А кто-нибудь может что-нибудь сказать по выше приведённому коду? Кажется это последняя ошибка которую видит valgrind (остальные все в GLcore).
> гониш, оптимизация ни как не влияет на отладочные символы
Как знаешь, но практика показывает что ни один отладчик (что gdb, что valgrind) при оптимизации уже не может точно определить к какой строке относится тот или иной объектный код.
Ты что, так только всё и оцениваешь? До сих пор работало, блин? Как тот альпинист, летящий в пропасть - "ну, пока всё в порядке"...
Полную гарантию тебе даст только:
- отсутствие арифметики указателей
- поддержка массивов и строк на уровне языка (проверка на переполнения)
Никакая библиотека и никакой дебаггер эти глюки самого языка не исправят. И если ты не знаешь досконально все слабые стороны Си, не знаешь, как защищаться от проблем такого рода, то тебе просто нельзя на Си писать. Понятно?
> И если ты не знаешь досконально все слабые стороны Си, не знаешь, как защищаться
> от проблем такого рода, то тебе просто нельзя на Си писать. Понятно?
Успокойся -- практика, практика и ещё раз практика, только так можно реально узнать как что может быть, а что нет.
Несомненно теория хороша, но без практики реального знания никогда не будет -- будет только "я слышал, что", "я читал, что", но не "я знаю, что". Вот так.
Можно сказать и так:
теория -- необходимое условие знания, а практика -- достаточное.
> Нельзя начинать, как ты, браться за практику без теории. Тренируйся пока на Java...
Ну, ну.. и чему я натренируюсь, когда за мной автоматически будут мусор подчищать?
Как раз что бы тренироваться убирать за собой мусор вручную, надо его убирать вручную!
Кстати ещё раз о моём не верном суждении по поводу valgrind. Я говорю до сих пор я не видел, чтобы он врал _на_моей_машине_, если сейчас я всё же найду ошибку, значит я уже буду _знать_ что это действительно бывает, что он чего-то не замечает, а до этого разумеется я предполагал, что в теории он может ошибаться.
> Изучи теорию - чтоб не предполагать, а знать. Ошибаться он может и должен, у него
> теоретически нет возможностей найти ВСЕ ошибки.
Все, нет, а вот утечек и неправильных использований указателей, по-моему, вполне возможно.
А что ты мне предложишь в качестве теоритического пособия: код ядра, код valgrind или документацию vaglrind?
Выведи значение укозателя возврата при входе в глякавую функцию и сразу перед выходом из её. Если различаются, а я полагаю что будут, налицо порчя стека.
Что ж, всем спасибо.
Проблема нашлась -- звёздочку я забыл :-)
То как я решал, конечно, эту проблему это смешно, но я поступил так как подсказывала мне природная лень:
так как в принципе без оптимизации всё работало, я решил не заморачиваться, а просто писать нужный мне код дальше -- ожидания меня не обманули -- сразу как только я завершил весь этот фрагмент, ошибка тут же всплыла, и с помощью gdb я уже узнал где берётся корень.
Конечно, тут возникал вопрос -- "и как вообще оно работало с этим?".
Ответ однако прост -- модуль в котором была допущена ошибка можно сказать не использовался в программе -- т.е. в нём происходила инициализация (ошибочно) некоторых данных, но затем они не использовались. Если бы я включил этот модуль (а выключен он временно), то ошибка тут же бы всплыла.