我有这个简单的程序,我试图保护一块内存,然后将文件读入该内存,在它发生段错误时释放它。 首先我认为如果文件是fifo只有一个问题..但现在看来,即使是普通文件也失败了,
这是代码:
#include <errno.h>
#include <string.h>
#include <iostream>
#include <assert.h>
#include <malloc.h>
#include <sys/mman.h>
#include <unistd.h>
#include <map>
#include <algorithm>
#include <unistd.h>
#include <signal.h>
using namespace std;
#define BUFFER_SIZE 8000
#define handle_error(msg) \
do { cout << __LINE__ << endl ;perror(msg); exit(EXIT_FAILURE); } while (0)
volatile int fault_count = 0;
char* buffer = 0;
int size = 40960;
int my_fault_handler(void* addr, int serious) {
if (mprotect(buffer, size,
PROT_READ | PROT_WRITE) == -1)
handle_error("mprotect");
++fault_count;
cout << "Segfaulting" << endl;
return 1;
}
static void handler(int sig, siginfo_t *si, void *unused) {
my_fault_handler(si ->si_addr, sig);
}
int main (int argc, char *argv[])
{
long pagesize = sysconf(_SC_PAGESIZE);
struct sigaction sa;
sa.sa_flags = SA_SIGINFO | SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = &handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
perror("sigaction");
cerr << "pageSize: " << pagesize << endl;
buffer = (char*)memalign(pagesize, size);
if (buffer == NULL)
handle_error("memalign");
if (mprotect(buffer, size, PROT_READ) == -1)
handle_error("mprotect");
FILE* file = fopen("test", "r");
cout << "File Open" << endl;
if (!file) {
cout << "Failed opening file " << strerror(errno) << endl;
return 0;
}
//*buffer = 0;
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
cout << ' ' << strerror(errno) << endl;
return(0);
}
注意// * buffer = 0;如果我取消标记此行程序段错误并正常工作.. 有谁有任何想法? 错误的地址是错误的。
谢谢!
更新 这里似乎有一个类似的问题: Loading MachineCode From File Into Memory and Executing in C -- mprotect Failing 在建议使用posix_memalign的地方,我试过了这个并且没有用。
答案 0 :(得分:2)
问题是您在短暂阅读后没有检查FILE
句柄中的错误。
系统告诉你的是第一个fread失败且没有触发错误处理程序。
如果您在循环外检查ferror
(以马虎为例):
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
if (ferror(file) != 0) {
cout << "Error" << endl;
}
失败的原因是基础read
失败了,并返回了14
(EFAULT
)的错误,这不是在这种情况下读取失败时记录的错误(它说Buf points outside the allocated address space.
)
当有问题的代码在用户上下文中运行时,您只能信任在mprotect情况下触发的信号处理程序,大多数系统调用将失败并返回EFAULT
缓冲区无效或没有正确权限的情况。