【问题标题】:Segmentation fault in reading a .dat file读取 .dat 文件时出现分段错误
【发布时间】:2013-11-18 23:35:19
【问题描述】:

现在,我正在编写一个示例代码,希望稍后将其集成到我的程序中。基本上我要做的是逐字节读取 .dat 文件并解释数据(即解释引导扇区以输出扇区大小、保留扇区等)

为此,我逐字节读取数据,并使用 https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html#ss1.3 的 fat12 中的描述,将数据转换为我想要的信息。现在,我可以从文件中提取单个字节(假设提取的数据是十六进制的是否正确?)。但是,我需要两个字节才能有意义。所以,我需要将两个字节合二为一,将十六进制数据转换为十进制并输出信息。不幸的是,现在,我遇到了段错误,对于我的生活,我无法弄清楚出了什么问题。提前致谢!

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

FILE *fp ,*fptest;
long lSize;
char *buffer;

//Open file
fptest= open("fat_volume.dat", "rb");

//Read file into buffer
fread(buffer,1,512,fptest);

//Parse the boot sector
char tmpA, tmpB;
tmpA = buffer[10]; //First byte
tmpB = buffer[11]; //Second byte

//Combine the two bytes into one
char combinedBytes[3];
strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);

//Hex to decimal converter
long int li1;
li1 = strtol (combinedBytes,NULL,16);
printf ("The sector size is: %ld.\n", li1);

return 0;

}

【问题讨论】:

  • 你永远不会 mallocbuffer 提供一个数组。一路走来,你需要说类似buffer = malloc(512);
  • 你能解释一下吗?我的C非常生锈。一个例子将不胜感激!
  • 您将自己定义为char*,但您从不将其指向任何东西。它可能指向某个未知位置,如果您尝试访问它,可能会打开一个虫洞。您需要将其设置为指向您拥有的一些内存。

标签: c


【解决方案1】:

你必须分配buffer;例如

char buffer[512];

char *buffer = malloc(512);

编辑:

字符串操作

strcpy (combinedBytes, tmpA);
strcat (combinedBytes, tmpB);

也没有任何意义,访问/复制太多数据(编译器会警告您!)。

我建议将值读取为

unsigned char tmpA = buffer[10];
unsigned char tmpB = buffer[11];

unsigned int tmp = (tmpA << 8) | (tmpB << 0);  /* or revert in in case of
                                                  little-endian */

为了让事情更有效率,我会把它写成

struct fat_header {
    uint8_t pad0[10];
    uint16_t my_val;
    uint8_t pad1[500];
} __attribute__((__packed__));      /* this is not portable and for gcc! */

...

struct fat_header  hdr;

fread(&hdr, 1, sizeof hdr, f);
uint16_t val = be16toh(hdr.my_val); /* or le16toh() in case of le */

【讨论】:

  • 嗨!我刚刚尝试了您的建议,但仍然出现段错误。有什么想法吗?
  • @user2989964:除此之外......退出str-whatevering单个字符。 char combinedBytes[] = { tmpA, tmpB, '\0' };
  • 您好,很抱歉问了这么多问题,您能解释一下吗?我主要用 Java 编程,所以我不太擅长 C。谢谢!
  • @user2989964:基本上...char*char 是两个完全不同的东西。您将单个 char 视为一个字符串 - 我想,这会提示编译器尝试将该 char 解释为指针,这使其再次脱轨。编译器应该吐出一大堆关于这些东西的警告。注意他们。
  • C 对类型的严格程度不如 Java。一切都只是一个数字,你需要小心你给它的数字类型。
【解决方案2】:

您正在读入一个您从未为其分配内存的缓冲区。

你现在尝试的是从内存中的一些垃圾值中读取,谁知道呢,这几乎总是会导致分段错误。

用途:

char *buffer = malloc(512 * sizeof(char)); // this allocates 512 times the size of a single char of memory

如果您没有将 malloc 中的数字指定为特定大小(例如 malloc(512),则该数字以字节为单位,但我认为最好始终包含它。

此特定错误称为dereferencing a null pointer

编辑:

我已经成功运行了这段代码:

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

int main (int argc, char **argv)
{  
    FILE *fp ,*fptest;
    long lSize;
    char *buffer;

    //Open file
    fptest = fopen("input.txt", "rb");

    if (fptest == NULL)
    {
        printf("Error occurred when opening file");
        return 1;
    }

    buffer = malloc(sizeof(char) * 512);
    //Read file into buffer
    fread(buffer,1,512,fptest);

    //Parse the boot sector
    char tmpA, tmpB;
    tmpA = buffer[10]; //First byte
    tmpB = buffer[11]; //Second byte

    //Combine the two bytes into one
    char combinedBytes[3];
    strcpy (combinedBytes, &tmpA);
    strcat (combinedBytes, &tmpB);

    //Hex to decimal converter
    long int li1;
    li1 = strtol (combinedBytes,NULL,16);
    printf ("The sector size is: %ld.\n", li1);

    return 0;
}

您还使用了函数open(),它必须是fopen(),并且您需要将tmpA和tmpB的地址传递给strcpy和strcat。

这就是为什么我不明白为什么你的编译器没有给出任何错误或警告..

【讨论】:

  • 不需要* sizeof(byte)。一个 char 定义为一个字节长。
  • 我个人认为它更整洁。
  • 嗨!我尝试了你的建议,但我仍然遇到段错误。有任何想法吗?顺便说一句,谢谢!
  • .dat 文件中有什么?当您尝试访问buffer[10] 等时,文件中是否有 11 个字符?我认为char combinedBytes[3] 太小了,因为它还必须带有空终止符。只需尝试将[3] 更改为[10] 之类的东西,看看会发生什么。尝试使用 GDB 来发现它在哪一行出现了段错误。
  • 只是一堆随机数据。我在这里尝试访问的是 .dat 文件的引导扇区。我正在学习文件系统,我应该确定 Fat12 .dat 文件的扇区大小、隐藏扇区等。但我只是逐字节解析文件。这就是我想用上面的代码做的事情。
猜你喜欢
  • 1970-01-01
  • 2020-08-14
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
相关资源
最近更新 更多