Hier ist der Beispielcode, den ich geschrieben habe.Warum führt eine Leseoperation auf einer speicherabgebildeten Null-Byte-Datei zu 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;
}
Wenn ich diesem Programm ein Nullbyte foo.txt gebe, endet es mit SIGBUS.
$ > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f8d882ab000
Bus error
Wenn ich diesem Programm ein Byte foo.txt gebe, dann gibt es kein solches Problem.
$ printf A > foo.txt && gcc foo.c && ./a.out
pagesize: 4096
data: 0x7f5f3b679000
65
0
0
48
56
10
mmap(2) erwähnt das folgende.
Verwendung einer abgebildeten Region kann in diesen Signalen resultieren:
SIGSEGV versuchtes Schreiben in einen Bereich, als schreibgeschützt abgebildet.
SIGBUS Versuchte Zugriff auf einen Teil des Puffers, der nicht mit der Datei übereinstimmt (z. B. über das Ende der Datei hinaus, einschließlich des Falls, bei dem ein anderer Prozess die Datei abgeschnitten hat).
Also wenn ich das richtig verstehen, auch der zweite Testfall (1-Byte-Datei) sollte SIGBUS geführt hat, weil und data[2]
versuchen, einen Teil des Puffers für den Zugriff (data
), das entspricht nicht die Datei.
Können Sie mir helfen zu verstehen, warum nur eine Null-Byte-Datei dazu führt, dass dieses Programm mit SIGBUS fehlschlägt?
Warum kümmert es dich? Sie rufen undefiniertes Verhalten auf; Alles kann passieren. Es ist nicht einmal garantiert, dass Sie überhaupt ein Signal bekommen. – Olaf
@Olaf Beim Lesen der [man-Seite] (https://linux.die.net/man/2/mmap) und der [POSIX-Dokumentation] (http://pubs.opengroup.org/onlinepubs/009695399/functions/ mmap.html), konnte ich nicht sicher sein, dass ich tatsächlich undefiniertes Verhalten anrufe. Die Manpage erwähnt nicht, dass ein solches Verhalten ein undefiniertes Verhalten ist. Dies gilt auch für die POSIX-Dokumentation. Nach meiner Interpretation der beiden Dokumente sollte ich für beide Tests "SIGBUS" in meiner Frage bekommen. –
POSIX basiert auf dem C-Standard, für den solche Zugriffe eindeutig UB sind. Sagte, dass es nicht klar ist, was Ihr Problem ist. Dein Code ist sowieso kaputt, wenn du einen SIGBUS oder SIGSEGV oder ähnliches bekommst, hast du schon alles vermasselt. Aber das ist nicht bijektiv: Wenn Sie kein Signal bekommen, bedeutet das nicht, dass Ihr Code korrekt ist! – Olaf