この質問への回答のほとんどは、次の重要なポイントについて述べています。C 標準には、セグメンテーション違反の概念が含まれていません。 (C99以降、シグナル番号 が含まれていますが、他の回答で説明されているようにカウントされないSIGSEGV
以外、そのシグナルが配信される状況は定義されていません。)raise(SIGSEGV)
したがって、セグメンテーション違反を引き起こすことが保証されている "厳密に準拠した" プログラム (つまり、動作が C 標準によって完全に定義されている構造のみを使用するプログラム) はありません。
セグメンテーション違反は、別の標準であるPOSIXによって定義されています。SIGBUS
このプログラムは、メモリ保護および高度なリアルタイム オプションを含む POSIX.1-2008 に完全に準拠しているシステムでは、セグメンテーション フォールトまたは機能的に同等の「バス エラー」( ) を引き起こすことが保証されていますsysconf
。posix_memalign
そしてmprotect
成功します。私のC99の解釈は、このプログラムはその標準のみを考慮した実装定義の(未定義ではない!)動作をしているため、準拠していますが、厳密には準拠していないということです。
#define _XOPEN_SOURCE 700
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
size_t pagesize = sysconf(_SC_PAGESIZE);
if (pagesize == (size_t)-1) {
fprintf(stderr, "sysconf: %s\n", strerror(errno));
return 1;
}
void *page;
int err = posix_memalign(&page, pagesize, pagesize);
if (err || !page) {
fprintf(stderr, "posix_memalign: %s\n", strerror(err));
return 1;
}
if (mprotect(page, pagesize, PROT_NONE)) {
fprintf(stderr, "mprotect: %s\n", strerror(errno));
return 1;
}
*(long *)page = 0xDEADBEEF;
return 0;
}