【问题标题】:Read Binary File - Segmentation fault读取二进制文件 - 分段错误
【发布时间】:2021-11-01 00:01:24
【问题描述】:

我正在尝试读取二进制文件的内容。我目前可以读取文件,但无法读取文件的全部内容,因为软件在终端返回错误(Segmentation fault),我的代码有什么问题?

我的输出:

0 0 0 0 0 0 0 0 0 0 a0 f2 41 0 0 0 0 0 88 be e8 b2 fd 7f 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b3 60 5f 7c 6 7f 0 0 0 0 0 0 0 0 0 0 88 be e8 b2 fd 7f 0 0 a0 c4 7b 7c 2 0 0 0 80 11 40 0 0 0 0 0 d0 12 40 0 0 0 0 0 49 d2 9f 81 bc c5 24 f0 90 10 40 0 0 0 0 0 80 be e8 b2 fd 7f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 49 d2 df fa 6d a0 df f 49 d2 51 41 2 3d 28 e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 88 be e8 b2 fd 7f 0 0 a0 be e8 b2 fd 7f 0 0 90 d1 98 7c 6 7f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 90 10 40 0 0 0 0 0 80 be e8 b2 fd 7f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 be 10 40 0 0 0 0 0 78 be e8 b2 fd 7f 0 0 1c 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 c3 dc e8 b2 fd 7f 0 0 cd dc e8 b2 fd 7f 0 0 0 0 0 0 0 0 0 0 d6 dc e8 b2 fd 7f 0 0 e6 dc e8 b2 fd 7f 0 0 f9 dc e8 b2 fd 7f 0 0 c dd e8 b2 fd 7f 0 0 21 dd e8 b2 fd 7f 0 0 43 dd e8 b2 fd 7f 0 0 5c dd e8 b2 fd 7f 0 0 6f dd e8 b2 fd 7f 0 0 99 dd e8 b2 fd 7f 0 0 f5 dd e8 b2 fd 7f 0 0 8 de e8 b2 fd 7f 0 0 24 de e8 b2 fd 7f 0 0 4c de e8 b2 fd 7f 0 0 68 de e8 b2 fd 7f 0 0 8b de e8 b2 fd 7f 0 0 a6 de e8 b2 fd 7f 0 0 c3 de e8 b2 fd 7f 0 0 dc de e8 b2 fd 7f 0 0 f3 de e8 b2 fd 7f 0 0 2a df e8 b2 fd 7f 0 0 43 df e8 b2 fd 7f 0 0 70 df e8 b2 fd 7f 0 0 81 df e8 b2 fd 7f 0 0 a1 df e8 b2 fd 7f 0 0 c4 df e8 b2 fd 7f 0 0 e3 df e8 b2 fd 7f 0 0 11 e0 e8 b2 fd 7f 0 0 29 e0 e8 b2 fd 7f 0 0 47 e0 e8 b2 fd 7f 0 0 60 e0 e8 b2 fd 7f 0 0 7f e0 e8 b2 fd 7f 0 0 9a e0 e8 b2 fd 7f 0 0 b4 e0 e8 b2 fd 7f 0 0 ce e0 e8 b2 fd 7f 0 0 97 e1 e8 b2 fd 7f 0 0 a7 e1 e8 b2 fd 7f 0 0 bb e1 e8 b2 fd 7f 0 0 ef e1 e8 b2 fd 7f 0 0 18 e2 e8 b2 fd 7f 0 0 2d e2 e8 b2 fd 7f 0 0 46 e2 e8 b2 fd 7f 0 0 aa e2 e8 b2 fd 7f 0 0 c0 e2 e8 b2 fd 7f 0 0 da e2 e8 b2 fd 7f 0 0 7 e3 e8 b2 fd 7f 0 0 26 e3 e8 b2 fd 7f 0 0 58 e3 e8 b2 fd 7f 0 0 85 e3 e8 b2 fd 7f 0 0 99 e3 e8 b2 fd 7f 0 0 b1 e3 e8 b2 fd 7f 0 0 da e3 e8 b2 fd 7f 0 0 e6 e3 e8 b2 fd 7f 0 0 6 e4 e8 b2 fd 7f 0 0 1c e4 e8 b2 fd 7f 0 0 2e e4 e8 b2 fd 7f 0 0 40 e4 e8 b2 fd 7f 0 0 65 e4 e8 b2 fd 7f 0 0 28 e5 e8 b2 fd 7f 0 0 47 e5 e8 b2 fd 7f 0 0 58 e5 e8 b2 fd 7f 0 0 71 e5 e8 b2 fd 7f 0 0 a4 e5 e8 b2 fd 7f 0 0 c4 e5 e8 b2 fd 7f 0 0 e9 e5 e8 b2 fd 7f 0 0 19 e6 e8 b2 fd 7f 0 0 35 e6 e8 b2 fd 7f 0 0 54 e6 e8 b2 fd 7f 0 0 79 e6 e8 b2 fd 7f 0 0 ac e6 e8 b2 fd 7f 0 0 c9 e6 e8 b2 fd 7f 0 0 fc e6 e8 b2 fd 7f 0 0 2d e7 e8 b2 fd 7f 0 0 44 e7 e8 b2 fd 7f 0 0 54 e7 e8 b2 fd 7f 0 0 68 e7 e8 b2 fd 7f 0 0 92 e7 e8 b2 fd 7f 0 0 9f e7 e8 b2 fd 7f 0 0 ba e7 e8 b2 fd 7f 0 0 ed e7 e8 b2 fd 7f 0 0 b8 e8 e8 b2 fd 7f 0 0 dc e8 e8 b2 fd 7f 0 0 f2 e8 e8 b2 fd 7f 0 0 1d e9 e8 b2 fd 7f 0 0 3b e9 e8 b2 fd 7f 0 0 64 e9 e8 b2 fd 7f 0 0 7a e9 e8 b2 fd 7f 0 0 8d e9 e8 b2 fd 7f 0 0 c4 e9 e8 b2 fd 7f 0 0 eb e9 e8 b2 fd 7f 0 0 fa e9 e8 b2 fd 7f 0 0 1e ea e8 b2 fd 7f 0 0 4a ea e8 b2 fd 7f 0 0 7e ea e8 b2 fd 7f 0 0 8f ea e8 b2 fd 7f 0 0 a0 ea e8 b2 fd 7f 0 0 b2 ea e8 b2 fd 7f 0 0 d2 ea e8 b2 fd 7f 0 0 dc ea e8 b2 fd 7f 0 0 e9 ea e8 b2 fd 7f 0 0 16 eb e8 b2 fd 7f 0 0 32 eb e8 b2 fd 7f 0 0 67 eb e8 b2 fd 7f 0 0 83 eb e8 b2 fd 7f 0 0 9d eb e8 b2 fd 7f 0 0 bf eb e8 b2 fd 7f 0 0 d1 eb e8 b2 fd 7f 0 0 e1 eb e8 b2 fd 7f 0 0 f6 eb e8 b2 fd 7f 0 0 8 ec e8 b2 fd 7f 0 0 2e ec e8 b2 fd 7f 0 0 56 ec e8 b2 fd 7f 0 0 71 ec e8 b2 fd 7f 0 0 84 ec e8 b2 fd 7f 0 0 9a ec e8 b2 fd 7f 0 0 b0 ec e8 b2 fd 7f 0 0 da ec e8 b2 fd 7f 0 0 f4 ec e8 b2 fd 7f 0 0 1e ed e8 b2 fd 7f 0 0 4e ed e8 b2 fd 7f 0 0 66 ed e8 b2 fd 7f 0 0 91 ed e8 b2 fd 7f 0 0 ab ed e8 b2 fd 7f 0 0 cc ed e8 b2 fd 7f 0 0 e6 ed e8 b2 fd 7f 0 0 7 ee e8 b2 fd 7f 0 0 3f ee e8 b2 fd 7f 0 0 5b ee e8 b2 fd 7f 0 0 7a ee e8 b2 fd 7f 0 0 8e ee e8 b2 fd 7f 0 0 a4 ee e8 b2 fd 7f 0 0 ba ee e8 b2 fd 7f 0 0 ce ee e8 b2 fd 7f 0 0 e5 ee e8 b2 fd 7f 0 0 ff ee e8 b2 fd 7f 0 0 27 ef e8 b2 fd 7f 0 0 38 ef e8 b2 fd 7f 0 0 f5 ef e8 b2 fd 7f 0 0 32 f0 e8 b2 fd 7f 0 0 4d f0 e8 b2 fd 7f 0 0 5f f0 e8 b2 fd 7f 0 0 8e f0 e8 b2 fd 7f 0 0 bd f0 e8 b2 fd 7f 0 0 d8 f0 e8 b2 fd 7f 0 0 15 f1 e8 b2 fd 7f 0 0 2e f1 e8 b2 fd 7f 0 0 58 f1 e8 b2 fd 7f 0 0 70 f1 e8 b2 fd 7f 0 0 8a f1 e8 b2 fd 7f 0 0 96 f1 e8 b2 fd 7f 0 0 b1 f1 e8 b2 fd 7f 0 0 df f1 e8 b2 fd 7f 0 0 fc f1 e8 b2 fd 7f 0 0 d f2 e8 b2 fd 7f 0 0 3e f2 e8 b2 fd 7f 0 0 4b f2 e8 b2 fd 7f 0 0 62 f2 e8 b2 fd 7f 0 0 8c f2 e8 b2 fd 7f 0 0 b8 f2 e8 b2 fd 7f 0 0 f2 f2 e8 b2 fd 7f 0 0 21 f3 e8 b2 fd 7f 0 0 42 f3 e8 b2 fd 7f 0 0 5b f3 e8 b2 fd 7f 0 0 6b f3 e8 b2 fd 7f 0 0 7c f3 e8 b2 fd 7f 0 0 96 f3 e8 b2 fd 7f 0 0 a1 f3 e8 b2 fd 7f 0 0 c4 f3 e8 b2 fd 7f 0 0 cc f3 e8 b2 fd 7f 0 0 f5 f3 e8 b2 fd 7f 0 0 16 f4 e8 b2 fd 7f 0 0 40 f4 e8 b2 fd 7f 0 0 4f f4 e8 b2 fd 7f 0 0 8f f4 e8 b2 fd 7f 0 0 b1 f4 e8 b2 fd 7f 0 0 cc f4 e8 b2 fd 7f 0 0 e1 f4 e8 b2 fd 7f 0 0 f8 f4 e8 b2 fd 7f 0 0 12 f5 e8 b2 fd 7f 0 0 3a f5 e8 b2 fd 7f 0 0 5d f5 e8 b2 fd 7f 0 0 df f5 e8 b2 fd 7f 0 0 b f6 e8 b2 fd 7f 0 0 45 f6 e8 b2 fd 7f 0 0 5c f6 e8 b2 fd 7f 0 0 75 f6 e8 b2 fd 7f 0 0 b1 f6 e8 b2 fd 7f 0 0 d6 f6 e8 b2 fd 7f 0 0 ef f6 e8 b2 fd 7f 0 0 61 f7 e8 b2 fd 7f 0 0 72 f7 e8 b2 fd 7f 0 0 bb f7 e8 b2 fd 7f 0 0 d9 f7 e8 b2 fd 7f 0 0 ea f7 e8 b2 fd 7f 0 0 3 f8 e8 b2 fd 7f 0 0 18 f8 e8 b2 fd 7f 0 0 33 f8 e8 b2 fd 7f 0 0 5b f8 e8 b2 fd 7f 0 0 77 f8 e8 b2 fd 7f 0 0 91 f8 e8 b2 fd 7f 0 0 a5 f8 e8 b2 fd 7f 0 0 bc f8 e8 b2 fd 7f 0 0 d2 f8 e8 b2 fd 7f 0 0 f4 f8 e8 b2 fd 7f 0 0 b f9 e8 b2 fd 7f 0 0 27 f9 e8 b2 fd 7f 0 0 4a f9 e8 b2 fd 7f 0 0 59 f9 e8 b2 fd 7f 0 0 7e f9 e8 b2 fd 7f 0 0 ab f9 e8 b2 fd 7f 0 0 cc f9 e8 b2 fd 7f 0 0 f4 f9 e8 b2 fd 7f 0 0 e fa e8 b2 fd 7f 0 0 22 fa e8 b2 fd 7f 0 0 52 fb e8 b2 fd 7f 0 0 89 fb e8 b2 fd 7f 0 0 c1 fb e8 b2 fd 7f 0 0 1b fc e8 b2 fd 7f 0 0 35 fc e8 b2 fd 7f 0 0 55 fc e8 b2 fd 7f 0 0 79 fc e8 b2 fd 7f 0 0 87 fc e8 b2 fd 7f 0 0 a7 fc e8 b2 fd 7f 0 0 d7 fc e8 b2 fd 7f 0 0 10 fd e8 b2 fd 7f 0 0 47 fd e8 b2 fd 7f 0 0 65 fd e8 b2 fd 7f 0 0 8e fd e8 b2 fd 7f 0 0 a4 fd e8 b2 fd 7f 0 0 ba fd e8 b2 fd 7f 0 0 e4 fd e8 b2 fd 7f 0 0 13 fe e8 b2 fd 7f 0 0 31 fe e8 b2 fd 7f 0 0 44 fe e8 b2 fd 7f 0 0 6a fe e8 b2 fd 7f 0 0 8b fe e8 b2 fd 7f 0 0 a2 fe e8 b2 fd 7f 0 0 c8 fe e8 b2 fd 7f 0 0 e2 fe e8 b2 fd 7f 0 0 fa fe e8 b2 fd 7f 0 0 36 ff e8 b2 fd 7f 0 0 4a ff e8 b2 fd 7f 0 0 5c ff e8 b2 fd 7f 0 0 91 ff e8 b2 fd 7f 0 0 ae ff e8 b2 fd 7f 0 0 c4 ff e8 b2 fd 7f 0 0 e2 ff e8 b2 fd 7f 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 e0 f5 b2 fd 7f 0 0 10 0 0 0 0 0 0 0 ff fb 8b 1f 0 0 0 0 6 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 11 0 0 0 0 0 0 0 64 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 40 0 40 0 0 0 0 0 4 0 0 0 0 0 0 0 38 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 b 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 e0 95 7c 6 7f 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 90 10 40 0 0 0 0 0 b 0 0 0 0 0 0 0 e8 3 0 0 0 0 0 0 c 0 0 0 0 0 0 0 e8 3 0 0 0 0 0 0 d 0 0 0 0 0 0 0 e8 3 0 0 0 0 0 0 e 0 0 0 0 0 0 0 e8 3 0 0 0 0 0 0 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 0 0 0 0 0 0 0 99 c7 e8 b2 fd 7f 0 0 1a 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1f 0 0 0 0 0 0 0 ee ff e8 b2 fd 7f 0 0 f 0 0 0 0 0 0 0 a9 c7 e8 b2 fd 7f 0 0 0 0 0 0 0 0 0 

我的代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf("Usage: Please insert the file to recover photos\n");
        return 1;
    }
    else
    {
        FILE *file;

        unsigned char buffer[10];

        file = fopen(argv[1], "rb");

        long posicao = ftell(file);

        printf("Ponteiro no Inicio %ld\n", posicao);

        fseek(file, 0, SEEK_END);

        posicao = ftell(file);

        printf("Ponteiro no Fim: %ld\n",posicao);

        //Cannot open file
        if (file == NULL)
        {
            printf("Cannot open file \n");
            exit(0);
        }
        else
        {
            //Read the content
            fread(buffer, sizeof(buffer), 1, file);

            for(int i = 0; i < posicao; i++)
            {
                printf("%x ", buffer[i]); // prints a series of bytes
            }
        }
    }
}

谢谢

【问题讨论】:

  • 您需要检查argv[1] 是否有效以及fopen 是否失败。实际上,您确实要检查fopen 是否在此处失败:if (file == NULL),但是为时已晚,您需要在fopen 之后立即进行检查。
  • for 循环中的posicao 可能比缓冲区的大小(即10)大得多?
  • 是的,我知道缓冲区[10] 很小,但我想过做这样的事情,但我不知道我是否做得对。缓冲区[ ] = posicao
  • 我在终端上添加了我正在获取的内容
  • 错误:表达式结果未使用 [-Werror,-Wunused-value] 缓冲区[posicao];

标签: c segmentation-fault binary-data


【解决方案1】:

以下建议代码:

  1. 消除冗余代码
  2. 正确获取文件长度
  3. 正确声明输入缓冲区
  4. 正确读取文件
  5. 正确使用从文件中读取的字节数来控制循环
  6. 不检查它应该检查的所有错误

缓冲区大小合适,可以容纳整个文件,因此缓冲区不会溢出。这种溢出会导致段错误事件。

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf("Usage: %s inputFileName\n Please insert the file to recover photos\n", argv[0]);
        return EXIT_FAILURE;
    }

    FILE file = fopen(argv[1], "rb");

    //Cannot open file
    if (file == NULL)
    {
        printf("Cannot open file \n"); // better to use perror()
        exit(0);  // 0 indicates success, better to use -1
    }       

    
    // move file pointer to end of file
    fseek(file, 0, SEEK_END);

    // get current file pointer location, relative to beginning of file
    long posicao = ftell(file);

    // move file pointer to start of file
    fseek(file, 0, SEEK_SET );
    
    printf("Ponteiro no Inicio %ld\n", posicao);

    // generate correct buffer size via a VLA (variable length array)
    unsigned char buffer[ posicao ];
    
    //Read the content and recover number of bytes read
    size_t bytesread = fread(buffer, sizeof(buffer), 1, file);

    // use number of bytes read as index limiter to display bytes
    for( size_t i = 0; i < bytesread; i++)
    {
        printf("%x ", buffer[i]); // prints a series of bytes
    }
}

【讨论】:

    【解决方案2】:
    1. 检查文件是否在使用fopen后立即打开(如问题cmets中所述)
    2. 使用fseek(file, 0, SEEK_END);后将光标移至文件开头
    3. 正确选择fread参数并获取其返回值:
    • fread(buffer, 1, sizeof(buffer), file);。其中sizeof(buffer) 是缓冲区的元素数。请参阅 @chux - Reinstate Monica 的评论和回答。如果缓冲区是动态分配的,sizeof(buffer) 将无法正常工作。
    • fread(buffer, sizeof(*buffer), sizeof(buffer), file);。使用sizeof(*buffer) 获取第一个元素的大小。
    • fread(buffer, 1, posicao, file);。如果 posicao
    1. 访问缓冲区直到读取的字节数。
      for (size_t i = 0; i &lt; readed; i++) printf("%x ", buffer[i]);。注意 @chux - Reinstate Monica 所说的 fread 返回(返回 size_t 八字节类型)

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[])
    {
        if (argc < 2)
        {
            printf("Usage: Please insert the file to recover photos\n");
            return 1;
        }
        else
        {
            FILE *file;
    
            file = fopen(argv[1], "rb");
    
            //Cannot open file --> check pointer file after fopen
            if (file == NULL)
            {
                printf("Cannot open file \n");
                exit(0);
            }
    
            long posicao = ftell(file);
    
            printf("Ponteiro no Inicio %ld\n", posicao);
    
            fseek(file, 0, SEEK_END);
    
            posicao = ftell(file);
    
            rewind (file); // Sets the position indicator associated with stream to the beginning of the file
    
            unsigned char buffer[posição]; // o buffer deveria ser criado aqui depois de pegar a posição final
    
            printf("Ponteiro no Fim: %ld\n",posicao);
    
            // Read the content --> é sempre bom verificar o valor lido
            // o terceiro parâmetro estava 1, deveria ser a "posicao"
            size_t readed = fread(buffer, sizeof(buffer), posicao, file);
    
            for(size_t i = 0; i < readed; i++) // usar readed como limite
            {
                printf("%x ", buffer[i]); // prints a series of bytes
            }
        }
    }
    

    参考资料:

    【讨论】:

    • fread(buffer, sizeof(buffer), posicao, file); 试图读取 posicao * posicao 字节。可能返回 1 而不是 posicao 的期望值。 fread() 的返回值可能超过 INT_MAX。当posicao == 0 时,unsigned char buffer[posicao]未定义的行为。有些文件的大小为 0。
    • sizeof(buffer) 返回 1(因为 buffer 是指向 unsigned char 的指针),而 position 将是文件中的字节数,因此会产生 1*position 字节。而int的位数是32,size_t的位数是16,所以fread的返回值不可能超过INT_MAXSIZE_MAX=65535,INT_MAX=2147483647。
    • @CodeMaker,因为是rewind(pFile),所以你应该是rewind(file)
    • 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。
    • Gean Santos,“sizeof(buffer) 返回 1(因为 buffer 是指向无符号字符的指针)”不正确。 buffer 是一个数组,而不是一个指针。 sizeof(buffer)posicao。试试printf("%zu\n", sizeof(buffer));
    【解决方案3】:

    代码试图写到buffer[] 的末尾。
    不要打印多于阅读。

    // fread(buffer, sizeof(buffer), 1, file);
    // for(int i = 0; i < posicao; i++)
    
    size_t n = fread(buffer, 1, sizeof(buffer), file);
    for(size_t i = 0; i < n; i++)
    

    在正确的地方添加错误检查。

    要读取超过 10 个,分配内存或使用可变长度数组 (VLA)。 VLA 需要进行更多测试,以确保其大小不是 0(容易),也不会太大(难以做到)。

        FILE *file = fopen(argv[1], "rb");
        if (file == NULL) {
            printf("Cannot open file\n");
            exit(EXIT_FAILURE);
        }
    
        if (fseek(file, 0, SEEK_END)) {
            printf("Cannot fseek\n");
            exit(EXIT_FAILURE);
        }
        rewind(file); // Go back to beginning
    
        long posicao = ftell(file);
        if (posicao == -1 || (unsigned long) posicao > SIZE_MAX) {
            printf("Trouble with ftell %ld\n", posicao);
            exit(EXIT_FAILURE);
        }
        size_t sz = (size_t) posicao;
        
        unsigned char *buffer == malloc(sz);
        if (buffer == NULL && sz > 0) {
            printf("Cannot malloc %zu\n", sz);
            exit(EXIT_FAILURE);
        } 
    
        printf("Size %zu\n", sz);
    
        size_t read_count = fread(buffer, 1, sz, file);
        if (read_count != sz) {
            printf("Size mis-match %zu %zu\n", sz, read_count);
        } 
        for (size_t i = 0; i < read_count; i++) {
            printf("%x ", buffer[i]);
        }
    
        free(buffer);
        fclose(file);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-17
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      • 1970-01-01
      相关资源
      最近更新 更多