【问题标题】:C memcpy() Segmentation FaultC memcpy() 分段错误
【发布时间】:2019-10-08 02:57:38
【问题描述】:

我一次又一次地遇到分段错误。 我的目的是将文件复制到共享内存中,以便另一个读取器进程可以读取它。 为了复制文件,我在 Struct 中分配了 M 大小的数据数组。 我使用了 NumberOfBuffers(N) 和 BufferSize(B),这样 M=N*B。 M 是文件的一半。所以文件大小约为2M。 我认为在这段代码中 memcpy() 正在生成分段错误。 最初我的目标是通过这个 Writer.c 在共享内存中达到完整的 M 大小,以查看 Copy 至少正在工作。 我的操作系统是 Ubuntu。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(void){
    struct MemData{
        char FileName[128];//POINTER PUTS DATA INTO NON-SHARED MEMORY
        int LastByteLength;
        int ReadPointer;
        int WritePointer;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    int BufferSize=51200;//FILE BUFFER SIZE 50 KB
    unsigned char Buf[BufferSize];

    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n");
        return EXIT_FAILURE;
    }
    fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO);
    if(ftruncate(SD, sizeof(MemData))< 0){
        printf ("ftruncate() error \n");
        return EXIT_FAILURE;
    }
    //THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }else{
        strcpy(M->FileName, "xaa");
        M->LastByteLength=0;
        M->ReadPointer=-1;
        M->WritePointer=-1;
        memset(M->Data, '\0', strlen(M->Data));
    }
    char FileName[128]="xaa";
    FILE *FP= fopen(FileName, "rb");
    if(FP!= NULL){
        struct stat StatBuf;
        if(stat(FileName, &StatBuf)==-1){
            printf("failed to fstat %s\n", FileName);
            exit(EXIT_FAILURE);
        }
        long long FileSize=StatBuf.st_size;
        printf("\n File Size: %lld", FileSize);
        long long FilePosition=ftell(FP);
        FilePosition=ftell(FP);
        long long CopyableMemorySize=FileSize-FilePosition;
        printf("\n Copyable File Size: %lld", CopyableMemorySize);
        int NumberOfFileBuffers=CopyableMemorySize/BufferSize;
        printf("\n Number Of File Buffers: %d", NumberOfFileBuffers);
        for(int i=0; i<NumberOfFileBuffers; i++){
            if(abs(M->WritePointer-M->ReadPointer)==NumberOfBuffers){
                //WAIT
            }else{
                fseek(FP, i*BufferSize, SEEK_SET);
                fread(Buf, sizeof(unsigned char), BufferSize, FP);
                memcpy(&M->Data[i*BufferSize], Buf, sizeof(Buf)*sizeof(unsigned char));
           }
        }
        fclose(FP);
    }
    close(SD);
    return 0;
}

【问题讨论】:

  • int BufferSize=51200; unsigned char Buf[BufferSize]; 从 VLA 移动到 malloc 以更好地处理堆栈外的情况。至于memcpy(&amp;M-&gt;Data[i*BufferSize], Buf, sizeof(Buf)*sizeof(unsigned char));,你为什么不简单地检查一下if (i*BufferSize*sizeof(Buf) &gt;= 512000) { error() }?您的代码中有一些 printf printf("\n Number Of File Buffers: %d", NumberOfFileBuffers); - 那么它们打印什么? NumberOfFileBuffers 的值是多少? FilePosition? CopyableMemorySize? sizeof(Buf)?
  • @KamilCuk 正在检查。
  • 这看起来很奇怪:memset(M-&gt;Data, '\0', strlen(M-&gt;Data)); 哪里写了一个字符串?最好使用缓冲区大小,或者如果它使字符串为空,只需将第一个元素设置为'\0'
  • @protik 对不起,你是对的,应该是+ 而不是*i * BufferSize + sizeof(Buf).
  • @protik 你应该尝试在上面运行一些调试工具,答案可能很容易出现。

标签: c ubuntu


【解决方案1】:

由于文件大小大于 NumberOfBuffers,那么这段代码需要 Mod Division 才能访问 M->Data 数组之外的数据。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(void){
    struct MemData{
        char FileName[128];//POINTER PUTS DATA INTO NON-SHARED MEMORY
        int LastByteLength;
        int ReadPointer;
        int WritePointer;
        char Data[512000];//MEMORY BLOCK SIZE: 500 KB
    };
    int SD;
    struct MemData *M;
    int NumberOfBuffers=10;
    int BufferSize=51200;//FILE BUFFER SIZE 50 KB
    unsigned char Buf[BufferSize];

    SD= shm_open("/program.shared", O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
    if(SD< 0){
        printf("\nshm_open() error \n");
        return EXIT_FAILURE;
    }
    fchmod(SD, S_IRWXU|S_IRWXG|S_IRWXO);
    if(ftruncate(SD, sizeof(MemData))< 0){
        printf ("ftruncate() error \n");
        return EXIT_FAILURE;
    }
    //THE FOLLOWING TYPECASTING AVOIDS THE NEED TO ATTACH THROUGH shmat() in shm.h HEADER I GUESS.
    M=(struct MemData*)mmap(NULL, sizeof(MemData), PROT_READ|PROT_WRITE, MAP_SHARED, SD, 0);
    if(M== MAP_FAILED){
        printf("mmap() error");
        return EXIT_FAILURE;
    }else{
        strcpy(M->FileName, "xaa");
        M->LastByteLength=0;
        M->ReadPointer=-1;
        M->WritePointer=-1;
        memset(M->Data, '\0', strlen(M->Data));
    }
    char FileName[128]="xaa";
    FILE *FP= fopen(FileName, "rb");
    if(FP!= NULL){
        struct stat StatBuf;
        if(stat(FileName, &StatBuf)==-1){
            printf("failed to fstat %s\n", FileName);
            exit(EXIT_FAILURE);
        }
        long long FileSize=StatBuf.st_size;
        printf("\n File Size: %lld", FileSize);
        long long FilePosition=ftell(FP);
        FilePosition=ftell(FP);
        long long CopyableMemorySize=FileSize-FilePosition;
        printf("\n Copyable File Size: %lld", CopyableMemorySize);
        int NumberOfFileBuffers=CopyableMemorySize/BufferSize;
        printf("\n Number Of File Buffers: %d", NumberOfFileBuffers);
        for(int i=0; i<NumberOfFileBuffers; i++){
            int BufferModCount=i%NumberOfBuffers;
            if(abs(M->WritePointer-M->ReadPointer)==NumberOfBuffers){
                //WAIT
            }else{
                fseek(FP, i*BufferSize, SEEK_SET);
                fread(Buf, sizeof(unsigned char), BufferSize, FP);
                printf("\n Checking: %d", i*BufferSize);

                memcpy(&M->Data[BufferModCount*BufferSize], &Buf, sizeof(Buf)*sizeof(unsigned char));
            }
        }
        fclose(FP);
    }
    close(SD);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多