Если вы еще не поняли, ошибка сегментации вызвана:
printf("blk: %p | %d\n", *&blk, blk);
Из-за вашей попытки вывести blk
(указатель на uint8_t
) как целое число . Несоответствие между типами аргументов и спецификатором формата printf
вызывает неопределенное поведение .
Стандарт C11 - 7.21.6.1 Fprintf
функция (p9) "
If a conversion specification is invalid, the behavior is undefined.
If any argument is not the correct type for the corresponding
conversion specification, the behavior is undefined."
Обратите внимание, что вы используете '*&'
перед blk
в этом утверждении излишне. Это просто blk
. Разыменование адреса указателя - это просто указатель. Вы можете исправить свое утверждение, чтобы напечатать адрес указателя и первый байт в blk
, используя правильные макросы точной ширины из inttypes.h
, например,
printf("blk: %p | 0x%02" PRIx8 "\n", (void*)blk, *blk);
В вашем распределении нет необходимости в fileSize + 1
, если только вы не собираетесь использовать хак для утвердительного ответа nul-terminate blk
, чтобы его можно было использовать в качестве строки. В некоторых случаях это может быть удобно, но обычно не рекомендуется. Когда ftell
возвращает количество байтов в файле, это все, что вам нужно выделить, если только вы не планируете добавить что-либо в конце. Кроме того, sizeof(uint8_t)
как sizeof(char)
всегда 1
- это тоже лишнее, например,
if (!(blk = malloc (filesize))) { /* validate allocation */
perror ("malloc-blk");
return 1;
}
Далее, WhozCraig пытался донести до вас, что каждый шаг должен быть проверен. При правильной проверке, нет никаких вопросов, где код терпит неудачу. Добавление проверок к каждому шагу будет выглядеть примерно так:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
int main (int argc, char **argv) {
uint8_t *blk;
long filesize;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (fseek (fp, 0, SEEK_END) == -1) { /* validate seek end */
perror ("fseek-SEEK_END");
return 1;
}
if ((filesize = ftell (fp)) == -1) { /* validate ftell */
perror ("ftell-fp");
return 1;
}
if (fseek (fp, 0, SEEK_SET) == -1) { /* validate seek set */
perror ("fseek-SEEK_SET");
return 1;
}
if (!(blk = malloc (filesize))) { /* validate allocation */
perror ("malloc-blk");
return 1;
}
if (fread (blk, 1, filesize, fp) != (size_t)filesize) { /* validate read */
perror ("fread-blk");
return 1;
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
/* do what you need with blk here */
printf("blk: %p | 0x%02" PRIx8 "\n", (void*)blk, *blk);
free (blk);
}
( примечание: не забудьте free (blk);
, когда вы закончите с его использованием)
Пример использования / Вывод
Выполнение кода как есть для любого файла просто выведет адрес указателя для blk
и первый байт в файле в шестнадцатеричном формате, например,
$ ./bin/rdfileintoblk ../dat/captnjack.txt
blk: 0x17e9240 | 0x54
Посмотрите вещи и дайте мне знать, если у вас есть какие-либо вопросы.