mmap的指针算术

7
最近我试图调整别人的mmap代码,但遇到了以下错误。(现在我对他们的代码有点怀疑,因为它看起来像是在做一些不必要的事情——试图使用自己的页面对齐内存和MAP_FIXED。manpage建议在Linux上将addr参数传入NULL应该可以实现这个功能。)所以我认为我至少会尝试用NULL地址调用mmap。然而,当我改变它时,我并不完全理解gcc抛出的错误。他们的代码可以正常工作,而我却得到了“需要左值作为赋值的左操作数”的错误提示。
基本上,他们正在做以下事情:
    uint8_t * ptr = (uint8_t *)mem;
    if ((uint32_t)ptr % PAGE_SIZE)
    {
        ptr += PAGE_SIZE - ((uint32_t)ptr % PAGE_SIZE);
    }

这里的mem是指一个void*类型的内存,该内存通过malloc函数分配。

我正在尝试使用类型转换来完成类似的操作:

    if ((uint32_t)mem % PAGE_SIZE)
    {   
        (uint8_t *)mem += PAGE_SIZE - ((uint32_t)mem % PAGE_SIZE); /* ERROR */
    }

所以我认为我很聪明地删除了一个我认为不需要的变量。 有人能告诉我为什么我的类型转换出错了吗? 谢谢。


2
这不是一个答案,但需要注意的是原始代码存在许多问题。他们的页面对齐代码会浪费整个页面,如果地址一开始就是页面对齐的话。而且,如果你不能确定永远不会释放内存,那么使用malloc获得的内存进行mmap(使用MAP_FIXED)可能是一个错误。 - R.. GitHub STOP HELPING ICE
1个回答

6

你犯的错误是:

(uint8_t *)mem += /* Anything.  */

你无法将类型转换的结果赋值给其他变量。类型转换后的结果和原始表达式的值不相同。

想象一下,如果这样做会有多奇怪:

(int) some_char_variable = 9999;

我曾经因为同样的原因遇到麻烦

使用一个临时变量,将结果写回,或者如R..在他们的评论中所说:

mem = (void *) ( ( (uint8_t *) mem) + SOME_EXPRESSION );

谢谢你,我需要一双新鲜的眼睛 :) 如果使用“+=”分离操作,会更好工作 :) - Alan
2
不需要临时变量,这样就可以工作:mem = (void *)((uint8_t *)mem + PAGE_SIZE - ((uint32_t)mem % PAGE_SIZE)); - R.. GitHub STOP HELPING ICE
1
这是一个“值”,与临时对象非常不同。 - R.. GitHub STOP HELPING ICE
2
顺便说一下,你选择的“我选择的解决方案”解决方案是错误的。这是一个别名违规,并会调用未定义的行为。如果这样做,现实世界的编译器可以生成不起作用的代码。 - R.. GitHub STOP HELPING ICE
2
是的,我认为那个答案是错误的。正确的答案只是 #define MY_DATA(bb) ( ((struct a_long_struct_name *) (bb)->aux) ) 而不是试图将 MY_DATA(bb) 用作 lvalue(因为它不是,也不能是)。相反,只需编写 bb->aux = malloc(...); 即可。 - R.. GitHub STOP HELPING ICE
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接