Целое число хранится как неправильное значение при использовании mmap - PullRequest
2 голосов
/ 19 апреля 2020

Я пишу программу, которая будет записывать массив структур в файл, используя mmap. Проблема в том, что третье целое значение (слева) не сохраняется должным образом. При просмотре файла через od байты в left кажутся смещенными на один байт влево. Например ...

|loc            |value  |left          |right          |extra bytes?
001 000 000 000 103 120 000 000 000 003 000 000 000 004 000 000 //expected
001 000 000 000 103 120 000 000 003 000 000 000 004 000 000 000 //result
typedef struct{
    int32_t loc;
    char value[2];
    int32_t left;
    int32_t right;

}Node;

Node newNode(int i);

int main(int argc, char *argv[])
{
    int i;
    int fd;
    int result;
    Node *map;  /* mmapped array of int's */

    int filesize = strtol(argv[2], NULL, 10) * sizeof(Node);
    int numvalues = filesize / sizeof(Node);

    fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    if (fd == -1) {
        perror("File failed to open");
        exit(1);
    }

    //I dont know why this makes it work but we need to move the file pointer around for some reason.
    result = lseek(fd, filesize-1, SEEK_SET);
    if (result == -1) {
        close(fd);
        perror("Error calling lseek()");
        exit(2);
    }

    // same with this
    result = write(fd, "", 1);

    /* Now the file is ready to be mmapped.
    */
    map = (Node *) mmap(0, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
        close(fd);
        perror("Error mmapping the file");
        exit(4);
    }


    for (i = 0; i <numvalues; ++i) {
        map[i] = newNode(i);         /* here is where I save the data */
    }

    munmap(map, filesize);
    close(fd);
    return 0;
}

Node newNode(int i) { /*This method is where the structs are made*/
    Node n;
    n.left = i * 2 + 1;
    n.right = i * 2 + 2;
    n.value[0] = (char)(rand() % ('A' - 'Z') )+ 'A';
    n.value[1] = (char)(rand() % ('A' - 'Z') )+ 'A';
    n.loc = i;

    printf("%d, %d, %c, %c, %d\n", n.left, n.right, n.value[0], n.value[1], n.loc);

    return n;
}

также, почему некоторые целые числа сохраняются как младшие и младшие порядковые числа.

1 Ответ

2 голосов
/ 19 апреля 2020

Вы столкнулись с двумя проблемами: порядком байтов и заполнением структуры.

Endianess

Кажется, ваша система имеет младший порядок байтов. Это означает, что младший байт сохраняется первым. Мы можем видеть это в том факте, что 1 хранится как 01 00 00 00. В системе с прямым порядком байтов это будет 00 00 00 01. Это означает, что ваш «ожидаемый» результат неверен. Это должно быть следующим. Обратите внимание, что левый и правый байты поменялись местами.

|loc            |value  |left          |right          |
001 000 000 000 103 120 003 000 000 000 004 000 000 000    

Заполнение структуры

Так почему бы не получить ожидаемый выше результат? Потому что компилятор добавляет отступ в структуре для выравнивания слов. Таким образом, после поля value есть два байта пэда. Распечатайте sizeof(Node) чтобы увидеть это. Следовательно, все фактически сдвинуто вправо на два байта. Таким образом, фактический ожидаемый результат:

|loc            |value  |pad     |left           |right          |
001 000 000 000 103 120  000 000 003 000 000 000 004 000 000 000    

Это именно тот результат, который вы показали.

...