Вот пример кода, который я написал.Почему операция чтения в файле с нулевым байтом с памятью приводит к SIGBUS?
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
int main()
{
int fd;
long pagesize;
char *data;
if ((fd = open("foo.txt", O_RDONLY)) == -1) {
perror("open");
return 1;
}
pagesize = sysconf(_SC_PAGESIZE);
printf("pagesize: %ld\n", pagesize);
data = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
printf("data: %p\n", data);
if (data == (void *) -1) {
perror("mmap");
return 1;
}
printf("%d\n", data[0]);
printf("%d\n", data[1]);
printf("%d\n", data[2]);
printf("%d\n", data[4096]);
printf("%d\n", data[4097]);
printf("%d\n", data[4098]);
return 0;
}
Если я предоставляю этому файлу нулевой байт foo.txt, он заканчивается SIGBUS.
$ > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f8d882ab000
Bus error
Если я предоставляю одну байту foo.txt для этой программы, то такой проблемы нет.
$ printf A > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f5f3b679000
65
0
0
48
56
10
mmap(2) упоминает следующее.
Использование отображенной области может привести к этим сигналам:
SIGSEGV Попытки записи в области отображается только для чтения.
SIGBUS Попытка доступа к части буфера, которая не соответствует файлу (например, за пределами файла, включая случай, когда другой процесс обрезал файл).
Так что, если я понимаю это правильно, даже второй тестовый случай (файл 1-байтового) должны были привести к SIGBUS потому и data[2]
пытаются получить доступ к части буфера (data
), что не соответствует файл.
Можете ли вы помочь мне понять, почему только файл с нулевым байтом заставляет эту программу терпеть неудачу с SIGBUS?
Зачем вам все это? Вы вызываете неопределенное поведение; все может случиться. Даже не гарантируется, что вы получите какой-либо сигнал. – Olaf
@Olaf При чтении [man page] (https://linux.die.net/man/2/mmap) и [документации POSIX] (http://pubs.opengroup.org/onlinepubs/009695399/functions/ mmap.html), я не мог быть уверен, что я действительно вызываю неопределенное поведение. На странице руководства не упоминается, что такое поведение является неопределенным поведением. Документация POSIX также отсутствует. Согласно моей интерпретации обеих документов, я должен получить «SIGBUS» для обоих тестов в моем вопросе. –
POSIX основан на стандарте C, для которого такие обращения явно UB. Сказал, что непонятно, какова ваша проблема. В любом случае, ваш код сломан, если вы получаете SIGBUS или SIGSEGV или что-то подобное, вы уже запутались. Но это не является биективным: если вы не получаете сигнал, это не значит, что ваш код правильный! – Olaf