4

我正在为一个文件实现一个基于日志的文件系统作为一个类项目。我在我的 64 位 OS X 笔记本电脑上运行了大量的代码,但是当我尝试在 CS 部门的 32 位 linux 机器上运行代码时,我遇到了一个段错误。

我们提供的 API 允许一次写入 DISK_SECTOR_SIZE (512) 字节。我们的日志记录包含用户想要写入的 512 字节以及一些元数据(他想要写入的扇区、操作类型等)。

总而言之,“记录”对象的大小是 528 字节,这意味着每条日志记录跨越磁盘上的 2 个扇区。

第一条记录在扇区 0 上写入 0-512,在扇区 1 上写入 0-15。第二条记录在扇区 1 上写入 16-512,在扇区 2 上写入 0-31。第三条记录在扇区 2 上写入 32-512,并且第 3 扇区的 0-47。ETC。

因此,我所做的是将要修改的两个扇区读入 2 个新分配的缓冲区,从记录开始复制到 buf1+计算出的 512 个偏移字节的偏移量。这在两台机器上都能正常工作。

但是,第二个 memcpy 失败了。具体来说,以下代码段错误中的“record+DISK_SECTOR_SIZE-offset”,但仅在 linux 机器上。运行一些随机测试,它变得更加好奇。linux 机器报告 sizeof(Record) 为 528。因此,如果我尝试将 record+500 的 memcpy 转换为 buf 1 个字节,它应该没有问题。

事实上,我可以从记录中获得的最大偏移量是 254。也就是说,memcpy(buf1, record+254, 1) 有效,但是 memcpy(buf1, record+255, 1) 段错误。

有谁知道我错过了什么?

Record *record = malloc(sizeof(Record));
record->tid = tid;
record->opType = OP_WRITE;
record->opArg = sector;
int i;
for (i = 0; i < DISK_SECTOR_SIZE; i++) {
  record->data[i] = buf[i]; // *buf is passed into this function
}

char* buf1 = malloc(DISK_SECTOR_SIZE);
char* buf2 = malloc(DISK_SECTOR_SIZE);

d_read(ad->disk, ad->curLogSector, buf1);  // API to read a specified sector into a buffer
d_read(ad->disk, ad->curLogSector+1, buf2);

memcpy(buf1+offset, record, DISK_SECTOR_SIZE-offset);
memcpy(buf2, record+DISK_SECTOR_SIZE-offset, offset+sizeof(Record)-sizeof(record->data));
4

4 回答 4

10

当您将 1 添加到指针 p 时,您不是在添加 1 个字节,而是在添加 sizeof(p) 个字节。

因此,在这种情况下,您需要先转换record为 a char*,然后再添加它。现在record+500实际上指向 500*528 = 264,000 字节record

当然,这并不能解释为什么memcpy(buf, record+254, 1)没有段错误。我猜只是“幸运”。

于 2010-04-08T18:07:40.550 回答
3

record+BLAH意思是,当翻译成机器码时:添加BLAH*sizeof(Record)record.

所以record+500不是 500 字节record;它距离 500*528 = 264000 字节record

于 2010-04-08T18:05:36.527 回答
2

尝试在下面运行您的 Linux 代码valgrind- 这应该可以让您直接找到问题的根本原因。

于 2010-04-08T18:05:00.660 回答
0

记录+DISK_SECTOR_SIZE-offset 是你的问题。记录+1 没有给出记录+1 的地址。

它给你和记录的地址+1*sizeof(record)。(当您递增或递减一个指针时,它会以您使用的数据类型的倍数步进。只需像这样对您的记录指针进行类型转换:(byte*)record+DISK_SECTOR_SIZE-offset。这可以解释分段错误,因为记录至少是 DISK_SECTOR_SIZE 长.

于 2010-04-08T18:31:57.933 回答