ntohl()从mmap()读取时返回0

时间:2018-03-28 02:32:27

标签: c++ memory mmap

晚上好,我正在尝试从.img文件中读取一些二进制信息。我可以从ntohs()中检索16位数字(uint16_t),但是当我尝试使用ntohl()从同一位置检索时,它会给我0代替。

以下是我的计划的关键部分。

#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <arpa/inet.h>
#include <cmath>

int fd;
struct blockInfo {
    long blockSize = 0;
    long blockCount = 0;
    long fatStart = 0;
    long fatBlocks = 0;
    long rootStart = 0;
    long rootBlocks = 0;
    long freeBlocks = 0;
    long resBlocks = 0;
    long alloBlocks = 0;
};


int main(int argc, char *argv[]) {

   fd = open(argv[1], O_RDWR);

   // Get file size
   struct stat buf{};
   stat(path, &buf);
   size_t size = buf.st_size;

   // A struct to hold data retrieved from a big endian image.
   blockInfo info;

   auto mapPointer = (char*) mmap(nullptr, size,
                     (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);

   info.blockSize = ntohs((uint16_t) mapPointer[12]);
   long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);

   printf("%ld", info.blockSize); // == 512, correct
   printf("%ld", anotherBlockSize); // == 0, what?
}

我知道blockSizeanotherBlockSize不应该相等,但anotherBlockSize至少应该是非零的,对吗?

还有别的,我去ntohs(pointer[16])访问数据,该数据应返回2,但也返回0.这里发生了什么?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

不,anotherBlockSize不一定非零

info.blockSize = ntohs((uint16_t) mapPointer[12]);

此代码相对于mapPointer从offset 12 读取一个char,将其强制转换为uint16_t并将ntohs()应用于它。

long anotherBlockSize = ntohl((uint32_t) mapPointer[11]);

此代码相对于mapPointer从offset 11 读取一个char,将其强制转换为uint32_t并将ntohl()应用于它。

显然,您正在从映射的内存中读取非重叠数据(不同的字符),因此您不应期望连接blockSizeanotherBlockSize

如果你试图以不同的方式读取相同的内存(如uint32_t和uint16_t),你必须做一些指针转换:

info.blockSize = ntohs( *((uint16_t*)&mapPointer[12]));

请注意,此类代码通常与平台有关。这种在x86上完美运行的转换可能在ARM上失败。

答案 1 :(得分:1)

auto mapPointer = (char*)  ...

这声明mapPointerchar *

... ntohl((uint32_t) mapPointer[11]);

这里你明显的意图是使用mapPointer从这个位置检索32位值,一个四字节值。

不幸的是,因为mapPointer是一个简单的花园种类char *,所以表达式mapPointer[11]会评估为单个孤独的char值。一个字节。这就是代码从mmap内存块读取的内容,在块起始的第11个偏移处。 (uint32_t)未从引用的地址uint32_t中读取mapPointer+11mapPointer[11]char读取一个mapPointer+11值,因为mapPointer是指向char的指针,将其转换为uint32_t,并且至ntohl()