0

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;
}
Zlorpo123
  • 47
  • 1
  • 6
  • Check that all the system calls succeeded, especially the `mmap`. – Nate Eldredge Dec 02 '20 at 06:17
  • You are not doing any error handling to make sure that `open()`, `creat()`, and `mmap()` are actually successful before calling `memcpy()` – Remy Lebeau Dec 02 '20 at 06:17
  • 1
    You have an `outstats` that is never defined, is it supposed to be `instats`? – Nate Eldredge Dec 02 '20 at 06:20
  • @RemyLebeau I've done some testing to make sure they are, and the file does get created with creat, I know it does open cause I outputted the data from the indata with cout and it showed it. My problem is that I'm attempting to do memcpy on a char* (out_data) and since that makes it read only, that doesn't work. – Zlorpo123 Dec 02 '20 at 06:20
  • @NateEldredge Fixed that, sorry – Zlorpo123 Dec 02 '20 at 06:21
  • @Zlorpo123 you are not creating read-only maps, so that is not the problem. But did you make sure `mmap()` is not returning NULL? – Remy Lebeau Dec 02 '20 at 06:22
  • Also, I cut off alot of the testing code that checked if open, creat, and mmap were successful to make it easier to read the code. – Zlorpo123 Dec 02 '20 at 06:23
  • You are running `memcpy` on a pointer you haven't allocated any space to. – Alex Reynolds Dec 02 '20 at 06:25
  • I'll bet you twenty bucks the `mmap` of `out_fd` failed. And I know why... – Nate Eldredge Dec 02 '20 at 06:25
  • @AlexReynolds Which pointer? For out_data I thought I did? Could you run me through that. – Zlorpo123 Dec 02 '20 at 06:26
  • @NateEldredge I just ran this under it: if(!out_data) { cout<<"\n"<<"mapping did not succeed"<<"\n"; exit(1); } And it finished to the end. Care to say why it failed? – Zlorpo123 Dec 02 '20 at 06:27
  • If you hadn't stripped out the error checking before posting, someone could have spotted that the error checking was wrong... – Nate Eldredge Dec 02 '20 at 06:33
  • Why are you using `mmap` and not standard `ifstream` and `ofstream`? They are about the same performance-wise. – nada Dec 02 '20 at 06:35
  • Its for purposes of using these libraries and practicing with them. Trust me I would've used those anyday. – Zlorpo123 Dec 02 '20 at 06:35

1 Answers1

2

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).

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82