如果我通过具有孔的结构类型的指针访问文件的存储器映射,则可能不会将结构元素映射到正确的数据。例如。
#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指令且不改变结构中元素的顺序的情况下避免这种情况。
答案 0 :(得分:2)
您基本上有以下选择:
__attribute__((packed))
或类似命令来控制编译器插入的填充(推荐,但要求您使用编译器扩展)在字节级别手动访问,不使用结构。例如:
char type;
int data;
memcpy(&type, ((char *)recPtr), 1);
memcpy(&data, ((char *)recPtr) + 1, sizeof(data));
答案 1 :(得分:1)
直接将二进制数据读入结构是一种灾难。这意味着你在没有验证的情况下对某些输入的结构做出假设;当然,您可以在事后检查结构的完整性。但通常情况下,您必须对输入数据进行体系结构相关调整。想想低端与大端。不同的字长,包装规则等
长话短说:不要为了黑暗的一面而堕落,这是诱惑快速黑客的承诺。
读取文件的唯一正确方法是用八位字节读取八位字节;您当然可以在缓冲区中读取更大的块,但是您应该通过查看每个位来处理它们。如果您担心性能问题,您应该阅读第1卷以及“计算机编程艺术”第4卷的内容,深入解释了如何有效地处理数据流而不忽略任何数据。
或使用Google的协议缓冲区。