【发布时间】:2011-02-05 20:02:43
【问题描述】:
我正在为一个文件实现一个基于日志的文件系统作为一个类项目。我在我的 64 位 OS X 笔记本电脑上运行了大量的代码,但是当我尝试在 CS 部门的 32 位 linux 机器上运行代码时,我遇到了 seg 错误。
我们提供的 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。 等等。
所以我要做的是将要修改的两个扇区读入 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));
【问题讨论】:
-
record + DISK_SECTOR_SIZE -offset 不会给你你需要放置 (byte*)record+(byte*)DISK_SECTOR_SIZE-(byte*)offset 的东西。当您添加到记录类型时,您会按 sizeof(record) 而不是 DISK_SECTOR_SIZE
-
代码在一个系统上没有出现段错误这一事实并不能说明一切。由于各种原因,错误代码有时会出现段错误,而其他时候则不会。
-
大卫的评论在这里非常正确。我还没有达到作业中的部分,即我读回我写到日志中的内容并重建内存中的对象——我之前写的内容在那时肯定会失败。
-
我的猜测是当越界内存访问达到操作码时会发生段错误,这是保护机制。
标签: c pointers segmentation-fault memcpy