доступ к области mmap с помощью указателя структуры - PullRequest
0 голосов
/ 20 июня 2011

Возможно, что если я получу доступ к карте памяти файла через указатель типа структуры с дырой, он может не сопоставить элементы структуры с корректными данными. Например,

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

typedef union{
    int a;
    char c[4];
}INT;

typedef struct{
    char type;
    INT data;
}RECORD;

int main(){
    int fd;
    RECORD *recPtr;
    fd = open("./f1", O_RDWR);
    if (fd == -1){
            printf("Open Failed!\n");
    }
    printf("Size of RECORD: %d\n", sizeof(RECORD));
    recPtr = (RECORD *)mmap(0, 2*sizeof(RECORD), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (recPtr == MAP_FAILED){
            printf("Map Filaed!\n");
    }
    printf("type: %c, data: %c%c%c%c\n", recPtr->type, recPtr->data.c[0], recPtr->data.c[1], recPtr->data.c[2], recPtr->data.c[3]);
}

Если файл "f1" содержит следующие данные:

012345678

Вышеуказанные программы выдают результат как

Size of RECORD: 8
type: 0, data: 4567

, поскольку символы 123 съедены отверстиями структуры.

Есть ли способ избежать этого без использования директивы pragma pack и без изменения порядка элементов в структуре.

Ответы [ 2 ]

2 голосов
/ 20 июня 2011

У вас есть следующие варианты:

  1. Примите дополнения. Это хорошо (и самый быстрый вариант), если ваши данные не нужно переносить между архитектурами.
  2. Использовать __attribute__((packed)) или аналогично управляющему заполнению, вставленному компилятором (рекомендуется, но требует использования расширений компилятора)
  3. Доступ вручную на уровне байтов, без использования структур. Например:

    char type;
    int data;
    
    memcpy(&type, ((char *)recPtr), 1);
    memcpy(&data, ((char *)recPtr) + 1, sizeof(data));
    
1 голос
/ 20 июня 2011

Чтение двоичных данных непосредственно в структуры - это путь к катастрофе. Это означает, что вы делаете предположения о структуре некоторых входных данных без проверки; конечно, вы можете проверить структуру на целостность впоследствии. Но чаще всего вам придется делать архитектурно-зависимые корректировки входных данных. Подумайте, младший или большой. Различные длины слова, правила упаковки и т. Д.

Короче говоря: не поддавайтесь на темную сторону, и это обещает быстрые взломы.

Единственный правильный способ чтения файла - это чтение его октетом по октету; Конечно, вы можете читать большие куски в буфере, но вы должны обработать их, просматривая каждый отдельный бит. Если вы беспокоитесь о производительности, вам следует прочитать Том 1 и то, что было выпущено до четвертого Тома «Искусство компьютерного программирования», в котором подробно объясняется, как эффективно обрабатывать потоки данных, не пренебрегая никакими данными.

Или используйте буфер протокола Google.

...