2017-11-12 4 views
-1

매핑 역 참조.분할 고장이 나는 세그먼트 오류를받지 않고 어떤 식 으로든 <code>mmap</code>에서 얻은 메모리를 액세스 할 수 없습니다 성가신 문제로 실행 해요 메모리

I는 메모리 맵핑을 얻기 위해 사용 된 함수는 다음과 같다.

/** 
    * Preconditions: filename must be verified as referencing a valid file. 
    */ 
    char *IOUtils::memory_map_file(string const& filename, size_t length, int open_flags){ 
    int fd = open(filename.c_str(), open_flags | O_CREAT, 
        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 
    int prot; 
    if (open_flags == O_RDONLY) 
     prot = PROT_READ; 
    else 
     prot = PROT_READ | PROT_WRITE; 
    void *output = mmap(NULL, length, prot, MAP_SHARED, fd, 0); 
    if (output == (void *) -1){ 
     cerr << filename << ": " << strerror(errno) << '\n'; 
     _exit(2); 
    } 
    close(fd); 
    return (char *)output; 
    } 

내 주요 기능은 다음과 같습니다.

int main(int argc, char *argv[]){ 
    size_t input_length = IOUtils::file_size(argv[1]); //This works fine 
    char *input_buffer = IOUtils::memory_map_file(argv[1], input_length, 
    O_RDONLY); //This succeeds 
    char *output_buffer = IOUtils::memory_map_file(argv[2], 2*input_length, 
    O_RDWR); //This succeeds 
    DomainParser parser(input_length, input_buffer, output_buffer); 
    while(!parser.finished()){ 
    parser.write_entry(); 
    } 
    mremap(output_buffer, 2*input_length, MREMAP_MAYMOVE, 
     parser.bytes_written()); 
    munmap(output_buffer, parser.bytes_written()); 
} 

파서의 관련 코드는이

void DomainParser::write_entry(void){ 
    char const *in = input(); //Gets position in input file 
    char const *copy_up_to = end(); //Gets position at input EOF 
    for(char const *it = in; it < copy_up_to; ++it){ 
     cerr << *it; //SIGSEGV! 
     if(*it == '\n') break; 
    } 
    cerr << '\n'; 
    /* Do writes */ 
} 

프로그램 세그먼테이션 폴트 (segfault) 바로시 cerr << *it 것 같습니다. 모든 매핑 된 메모리가 읽기 권한을 갖추고 있고 성공적으로 할당 되었기 때문에 이것이 일어날 이유가 없습니다.

편집 : 사람이 여기에, 클래스가 어딘가 고장이 의심 전체 소스 코드의 경우.

using std::stringstream; 
using std::string; 

class DomainParser{ 
    size_t _input_offset; 
    const size_t _input_length; 
    size_t _output_offset; 
    char const *input_buffer; 
    char *output_buffer; 

    char const *input(void){ 
    return input_buffer + _input_offset; 
    } 

    char *output(void){ 
    return output_buffer + _output_offset; 
    } 

    char const* end(void){ 
    return input_buffer + _input_length; 
    } 

    char const *find(char const *begin, char const *max, char c){ 
    while (*begin != c){ 
     cerr << *begin++; 
    } 
    cerr << c; 
    return begin; 
    } 

public: 
    DomainParser(size_t length, char const *input, char *output) : 
    _input_length(length), input_buffer(input), output_buffer(output) 
    {} 

    bool finished(void){ 
    return _input_offset == _input_length; 
    } 

    size_t bytes_written(void){ 
    return _output_offset; 
    } 

    size_t write_entry(void){ 
    if (finished()){ 
     return 0; 
    } 
    char const *in = input(); 
    char const *copy_up_to = find(in, end(), '\n'); 
    size_t input_entry_length = copy_up_to - in; 

    string s(in, copy_up_to); 
    stringstream ss(s); 
    string name, type, host; 
    ss >> name >> type >> host; 
    if (!ss){ 
     cerr << s << '\n'; 
     _input_offset += input_entry_length; 
     return 0; 
    } 
    ss.str(""); ss.clear(); 
    ss << "{\"name\":\"" << name << "\"," << 
     "\"host\":\"" << host << "\"," << 
     "\"type\":\"" << type << "\"}\n"; 
    string entry = ss.str(); 
    std::memcpy(output(), entry.c_str(), entry.size()); 

    _input_offset += input_entry_length; 
    _output_offset += entry.size(); 
    return entry.size(); 
    } 
}; 
+2

공유 메모리와 어떤 관계가 있습니까 ?? 아마도'char const * in = input(); '과의 에러이고'input()'이하는 것을 우리에게 보여주지는 않을 것입니다. –

+0

@ Paul Ogilvie 어떤 종류의 질문입니까? 매핑 된 메모리를 역 참조 할 때 segfault가 발생합니다. 참고로, input()은'{return input_buffer + _input_offset} '으로 정의됩니다. offset은 처음에는 0이고, 버퍼는'mmap'에서 반환 된 버퍼와 같습니다. – Navneeth

+2

매핑에 문제가 있는지 쉽게 확인할 수 있습니다. 첫 번째 및 마지막으로 매핑 된 버퍼 바이트를 다음과 같이 'main'에서 검색 한 직후에 읽습니다. assert (0 VTT

답변

0

나는 _input_offset의 초기화가 표시되지 않습니다. 당신이 것을 해결하는 경우

, 당신은 그래서 SIGBUS 신호를 트리거 할 모든 페이지에 액세스 출력 파일이 비어있는 문제로 실행됩니다. 원하는 크기로 ftruncate을 사용하여 크기를 조정해야합니다 (매핑의 크기와 일치하기는하지만 실제로하려는 작업에 따라 다릅니다).

또한 munmap은 매우 비쌀 수 있습니다 (특히 대형 시스템에서). 따라서 메모리 매핑 I/O는 파일 크기가 매우 클 경우에만 유리합니다.

관련 문제