使用 mmap 时整数存储为不正确的值
Integer stored as incorrect value in when using mmap
我正在编写一个程序,使用 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
存储为 01 00 00 00
的事实中看出这一点。在大端系统中,它将是 00 00 00 01
。这意味着您的 "expected" 结果不正确。它应该如下所示。注意左右字节已经交换了。
|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
这正是您显示的实际结果。
我正在编写一个程序,使用 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
存储为 01 00 00 00
的事实中看出这一点。在大端系统中,它将是 00 00 00 01
。这意味着您的 "expected" 结果不正确。它应该如下所示。注意左右字节已经交换了。
|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
这正是您显示的实际结果。