Search code examples
c++filemmapmemcpy

Memcpy segmentation fault even when memory is allocated


I'm attempting to copy the data from one file by writing it to memory and then copy it into another using memcpy but I'm stumped. I cannot get it to stop giving me segmentation fault. I have a feeling it has something to do with the allocated memory, but I also made sure the file size of the output file is the same as the first one so it wouldn't have that problem and can paste the data into it.

edit: I've come to figure it has to do with char out_data and how I'm attempting to copy data into it when it is read only. Not sure how to go about this.

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <chrono>
using namespace std;
using namespace std::chrono;



#define OUTPUT_MODE 0700         // protection bits for output file

int main(int argc, char** argv)
{

  auto start = high_resolution_clock::now();
    /* Open the specified file */
    int fd = open(argv[1], O_RDWR);



    // stats.st_size is a variable containing the size of inFile.txt
    struct stat instats;
    if (stat(argv[1], &instats)==0)
            cout<<endl<<"inFile size "<<instats.st_size;
    else
           cout<<"Unable to get file properties.\n";



    /* Get the page size  */
    int pagesize = getpagesize();
    cout<<endl<<"page size is " <<pagesize<<"\n";

    /******************Creation of outFile.txt******************/
    int out_fd = creat(argv[2], OUTPUT_MODE);


    char* in_data = (char*)mmap(NULL, instats.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    ftruncate(out_fd, instats.st_size);


    char* out_data = (char*)mmap(NULL, instats.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, out_fd, 0);


// THIS LINE IS THE CULPRIT 
    memcpy(out_data, in_data, instats.st_size);


    /* Unmap the shared memory region */
    munmap(in_data, instats.st_size);
    munmap(out_data, instats.st_size);

    /* Close the file */
    close(fd);
    close(out_fd);

    return 0;
}

Solution

  • creat creates a file which is only open for writing. You cannot mmap such a file descriptor because there is no such thing as write-only memory. If you were to check the return value from the mmap of out_fd, you would find that it failed, with errno == EACCES. When mmap fails it returns an invalid pointer MAP_FAILED (not NULL but typically -1) which causes a segfault when memcpy attempts to write there.

    Note that if (!out_data) is therefore the wrong test for failure of mmap; you must use if (out_data == MAP_FAILED).

    Instead of creat, use open(argv[2], O_RDWR | O_CREAT | O_TRUNC, OUTPUT_MODE).