Итак, мне трудно понять, в чем смысл ошибок, которые мне дает valgrind.
Мой код получает файл судоку и проверяет его правильность или нет. Он получает имя файла в командной строке, открывает его и делает все, что должен, а именно проверяет его правильность.
Пример:
./run sudoku.txt
Код работает абсолютно нормально, но когда я запустил valgrind, он выдал две ошибки, которые я вообще не понял, но я предположил, что это связано с обработкой файлов.
Вот запуск valgrind:
==20853== Syscall param openat(filename) points to unaddressable byte(s)
==20853== at 0x4F4BD9E: open (open64.c:47)
==20853== by 0x4EC85F9: _IO_file_open (fileops.c:189)
==20853== by 0x4EC85F9: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:281)
==20853== by 0x4EBAF19: __fopen_internal (iofopen.c:78)
==20853== by 0x4EBAF19: fopen@@GLIBC_2.2.5 (iofopen.c:89)
==20853== by 0x108BD1: main (q1_acs2.c:90)
==20853== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==20853==
==20853== Invalid read of size 4
==20853== at 0x4EB82BD: __isoc99_fscanf (isoc99_fscanf.c:30)
==20853== by 0x108D4E: main (q1_acs2.c:96)
==20853== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==20853==
==20853==
==20853== Process terminating with default action of signal 11 (SIGSEGV)
==20853== Access not within mapped region at address 0x0
==20853== at 0x4EB82BD: __isoc99_fscanf (isoc99_fscanf.c:30)
==20853== by 0x108D4E: main (q1_acs2.c:96)
==20853== If you believe this happened as a result of a stack
==20853== overflow in your program's main thread (unlikely but
==20853== possible), you can try to increase the size of the
==20853== main thread stack using the --main-stacksize= flag.
==20853== The main thread stack size used in this run was 8388608.
==20853==
==20853== HEAP SUMMARY:
==20853== in use at exit: 0 bytes in 0 blocks
==20853== total heap usage: 1 allocs, 1 frees, 552 bytes allocated
==20853==
==20853== All heap blocks were freed -- no leaks are possible
==20853==
==20853== For counts of detected and suppressed errors, rerun with: -v
==20853== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
Segmentation Fault
А вот часть моего кода, где я открываю файл и сохраняю его в матрице: (Я добавлю номера строк, чтобы вы могли видеть, где они указывают на ошибки)
85 int main(int argc, char *argv[])
86 {
87 int r = 9, c = 9, flag = 0;
88 FILE *px;
89
90 px = fopen(argv[1], "r");
91 int mat[r][c];
92
93 for (int i = 0; i < r; i++) {
94 for (int j = 0; j < c; j++)
95 if (j < 8)
96 fscanf(px, "%d,", &mat[i][j]);
97 else
98 fscanf(px, "%d", &mat[i][j]);
99 }
100 fclose(px);
В чем смысл заявления if (j <8)
? Вы делаете то же самое в if
и else
.
@Barmar: числа в строке разделяются запятыми. Для всех, кроме последнего, тоже читайте запятую. Хотя вы можете обойтись без буквального совпадения запятой с последним числом в строке (у fscanf()
нет возможности сообщить об этом с помощью формата "%d,"
), это довольно тонко. На самом деле, вы бы сошли с рук с данными, разделенными пробелами или запятыми (или смесью), как они есть, если в конце строки нет запятой.
Почему бы не прочитать всю строку в формате "%d,%d,%d,%d,%d,%d,%d,%d,%d"
?
@JonathanLeffler да, это все
Я ПОНЯЛ, В ЧЕМ БЫЛА ПРОБЛЕМА. Это было так глупо... я немного смущен. Я забыл запустить valgrind с именем файла. Так что я должен был запустить как: valgrind ./run sudoku.txt Тот, кто заставил меня найти глупую проблему, был @JonathanLeffler, спасибо! Спасибо всем, кто прокомментировал
Несмотря на то, что вы предлагаете в тексте, вывод Valgrind показывает, что вы не передали аргумент в программу. Вы не проверили, что argv[1]
допустимо, прежде чем передать его fopen()
. Поскольку вы пропустили аргумент имени файла, argv[1]
является нулевым указателем, и система возражает против вас, используя нулевой указатель.
==20853== Address 0x0 is not stack'd, malloc'd or (recently) free'd
Нулевой указатель... В ошибках сообщается обо всех упоминаниях «адрес 0x0»; ваш код не выполняет соответствующую проверку ошибок.
Вы также не проверяете, что fopen()
удалось, что вызовет проблемы, если данный файл не открывается. Вы также не проверяете успешность вызовов fscanf()
; это тоже может вызвать проблемы, если содержимое файла не соответствует вашим ожиданиям.
Если, как вы утверждаете, вы передали имя файла программе, вы увидите его в верхней части вывода Valgrind. Вы не показали эту информацию.
argv[1] — это «sudoku.txt»
@ John3136: так говорит ОП. Вальгринд говорит иначе.
@JonathanLeffler Чувак, я действительно смущен. Я забыл запустить valgrind с именем файла... Не знаю, гнилой ли у меня мозг, но знаете, бывает. Большое спасибо, вы тот, кто заставил меня узнать это! Я поставлю ваш ответ как правильный ответ!
@RhynoProgrammin — всякое бывает. Пусть первыми бросят камни те, кто никогда не совершал подобной ошибки. Теперь вы знаете, почему вы выполняете проверку ошибок в своем коде.
Да, именно. Еще раз спасибо, @JonathanLeffler!.
Я думаю, вы пропустили проверку возвращаемого значения fscanf
; поместите это в утверждение if
:
if (fscanf(fp, "%d", &value) == 1)
Затем результат будет проверен и не будет расширяться целым числом.
Первая зарегистрированная ошибка связана с fopen()
. Проблема, связанная с fscanf()
, заключается в передаче нулевого указателя в качестве файлового потока.
Проверьте указатель файла после
fopen()
. Проблема с файлом (от Valgrind).