Ошибка сегментации мемкпи на Linux, но не OS X
-
25-09-2019 - |
Вопрос
Я работаю над реализацией файловой системы на основе журнала для файла в качестве класса. У меня есть хорошее количество его работы на моем 64-битной OS X ноутбуке, но когда я пытаюсь запустить код на 32-битных машинах отдела CS 32-битных Linux, я получаю ошибку SEG.
API, которым мы предоставляем, позволяет написать байты Disk_sector_size (512) одновременно. Наша запись журнала состоит из 512 байтов, которые пользователь хочет написать, а также некоторые метаданные (каким сектором он хочет написать, типом эксплуатации и т. Д.).
В целом размер объекта «Record» составляет 528 байт, что означает, что каждый журнал записи охватывает 2 сектора на диске.
Первая запись пишет 0-512 на сектор 0, а 0-15 по сектору 1. Вторая запись записывает 16-512 на сектор 1, а 0-31 на секторе 2. Третья запись записывает 32-512 на сектор 2, а также 0-47 на сектор 3. И т. Д.
Итак, что я делаю, это прочитать два сектора, я буду изменять на 2 свежевыделенных буфера, скопируйте, начиная с записи в Buf1 + рассчитанное смещение для 512-офсетных байтов. Это работает правильно на обеих машинах.
Однако вторая мемкпи не удается. В частности, «Record + Disk_sector_size-offset» в следующем коду SegFaults, но только на машине Linux. Запуск каких-либо случайных тестов, становится все более любопытно. Машина Linux отчеты SIZEOF (запись), чтобы быть 528. Следовательно, если я попробовал meMcpy из записи + 500 в Buf для 1 байта, у него не должно быть проблемой.
На самом деле, самое большое смещение, которое я могу получить от записи, составляет 254. То есть memcpy (Buf1, запись + 254, 1) работает, но memcpy (BUF1, запись + 255, 1) Segfaults.
Кто-нибудь знает, чего мне не хватает?
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));
Решение
Когда вы добавляете 1 к указателю P, вы не добавляете 1 байт, вы добавляете BYTES SIZEOF (P).
Так что в этом случае вам нужно бросить record
к А. char*
перед добавлением к нему. Прямо сейчас record+500
на самом деле очки 500 * 528 = 264 000 байтов вдали от record
.
Конечно, это не объясняет, почему memcpy(buf, record+254, 1)
не SegFault. Просто «повезло», я думаю.
Другие советы
record+BLAH
Средства, когда переведено в машинный код: Добавить BLAH*sizeof(Record)
по адресу в record
.
Так record+500
не 500 байт от record
; Это 500 * 528 = 264000 байтов от record
.
Попробуйте запускать свой код Linux под valgrind
- это должно поднять вас прямо к исчезновению проблемы.
Запись + disk_sector_size-offset - ваша проблема. Запись + 1 не дает и адрес записи + 1.
Это дает вам и адрес записи + 1 * SizeOf (запись). (Когда вы увеличиваете или уменьшите указатель, который он работает в нескольких шагах данных, введите ваше использование. Просто типографское указатель записи, как так: (байт *) Запись + disk_sector_size-offet. Это объяснило бы ошибку сегментации, поскольку запись не менее Disk_sector_size Отказ