Итак, в этом довольно большом исходном файле у меня есть следующий раздел, скажем, в функции foo
, которая вызывается из main
:
FILE *logfile = NULL
if (log_engabled) {
char fname[30];
snprintf(fname, 30, ".logs/%d.txt", time(NULL));
logfile = fopen(fname, "w");
}
fprintf(logfile, "test\n");
Это выполняется без проблем.(Да, я должен остерегаться logfile == NULL
, но для краткости я это опустил).В моих тестовых прогонах log_file == 0x840fa50
и &log_file == 0x7ffffffedca8
.
Затем я вызываю другую функцию, bar
, которая принимает несколько аргументов, включая FILE **log_stream
.Его тело выглядит так:
if (*log_stream)
fprintf(*log_stream, "test\n");
/*a bunch of other stuff, including more fprintf calls*/
Теперь вот странная часть.Если я позвоню bar
из foo
непосредственно после указанного выше сегмента кода, все пройдет гладко.Однако на более позднем этапе в foo
снова вызывается bar
с другими параметрами, но с тем же указателем logfile
.Тогда я получаю SIGSEGV
прямо на fprintf
звонок.Я проверил с помощью gdb, и расположение указателя точно такое же, как и значение, на которое он указывает (и я никогда не называю fclose
между).
Что может быть причиной такого поведения?Это должно быть связано с кодом, который я выполняю между вызовами bar
, но ни одно из этих утверждений не включает logfile
во что-либо, кроме fprintf
вызовов.
Может быть, я вызываю segfaultгде-то, кроме вызова fprintf
, и GDB дает мне неправильный номер строки, но я скомпилировал с помощью gcc -O0 и -g, и когда я перемещаю оператор print, появляется сообщение об ошибке.
Я также попытался объявить logfile
глобальной переменной и не передавать ее в bar
, но безрезультатно.Любая помощь приветствуется.
РЕДАКТИРОВАТЬ:
Я немного покопался и * барабанная дробь * - Проблема была вызвана потерей целочисленного значения без знака, вызвавшей выход иззапись в массив диапазонов.Более конкретно:
foo() {
FILE *logfile = fopen("log.txt", "w");
fprintf(logfile, "test1");
memory_corrupting_function();
fprintf(logfile, "test2");
}
Первый fprintf
снова проходит гладко, а второй вызывает SIGSEGV
.Итак, перефразируя мой первоначальный вопрос: если я не вызываю fprintf
снова, то, как программы продолжают нормально работать, почему произошла ошибка, когда я вызываю fprintf
, а не когда пишу в недопустимую область памяти?
Есть ли даже ответ или это просто неопределенное поведение, которое меняется в разных реализациях?