0

我有一个简单的程序,我试图保护一块内存,然后将一个文件读入该内存,当它出现段错误时释放它..首先我认为如果文件是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;,如果我取消标记这一行,程序会出现段错误并正常工作..有人知道吗?errno 是错误的地址。

谢谢!

更新: 这里似乎问了一个类似的问题: Loading MachineCode From File Into Memory and Executing in C -- mprotect Failing where posix_memalign isSuggested,我试过这个但没有用。

4

1 回答 1

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的 errno ,这与在这种情况下读取失败时记录的情况并不完全一致(它说)14EFAULTBuf points outside the allocated address space.

当有问题的代码在用户上下文中运行时,您只能信任在 mprotect 情况下触发的信号处理程序,大多数系统调用将EFAULT在缓冲区无效或没有正确权限的情况下失败并返回。

于 2014-04-23T09:17:05.023 回答