将长int转换为void*

Casting a long int to void *

本文关键字:void 转换 int 将长      更新时间:2023-10-16

这是将long强制转换为void *的正确方法吗?在Qt程序中使用-O2时,我遇到了segfault。当使用-O1时,它不会segfault。

当使用reinterpret_cast<void *>(tp.tv_nsec)时,我也使用-O2得到一个segfault。

为什么会出现segfault?

timespec tp; // struct that holds nanoseconds since Epoch
clock_gettime(CLOCK_REALTIME, &tp); // tv_nsec is a long int
void *test = mmap((void *)(tp.tv_nsec), 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
printf("%pn", test);
printf("%lin", (long)test);

编辑:AFAIK,目标似乎表达错误。目标是获得一个随机数,以便分配一个随机存储器地址。这样,每当我在整个测试程序中多次使用mmap()时,我都会得到一个随机内存地址。如果不是,mmap()似乎会按顺序分配内存。

转换无效,因为tp.tv_nsec不是地址:

mmap((void *)(tp.tv_nsec), 4096,
                 ^ 
                 |  is not an address

试试这个:

mmap((void *) &(tp.tv_nsec), 4096,
              ^
              |  amperson operator for address

&是(操作数的)地址运算符给出变量的地址

我不想知道为什么要将变量强制转换为地址变量,但您的优化设置之一是反对这一点的:

-O2打开-O指定的所有优化标志。它还打开以下优化标志:

      -fthread-jumps 
      -falign-functions  -falign-jumps 
      -falign-loops  -falign-labels 
      -fcaller-saves 
      -fcrossjumping 
      -fcse-follow-jumps  -fcse-skip-blocks 
      -fdelete-null-pointer-checks 
      -fdevirtualize 
      -fexpensive-optimizations 
      -fgcse  -fgcse-lm  
      -fhoist-adjacent-loads 
      -finline-small-functions  ----------> Result: this is causing the segfault(elaine has found so +1 to him please).
      -findirect-inlining 
      -fipa-sra 
      -foptimize-sibling-calls 
      -fpartial-inlining 
      -fpeephole2 
      -fregmove 
      -freorder-blocks  -freorder-functions 
      -frerun-cse-after-loop  
      -fsched-interblock  -fsched-spec 
      -fschedule-insns  -fschedule-insns2 
      -fstrict-aliasing                 --------> I thought this was issue(void * from long) but is not
      -fstrict-overflow 
      -ftree-switch-conversion -ftree-tail-merge 
      -ftree-pre 
      -ftree-vrp

我怀疑:

-fsstrict混叠允许编译器采用适用于正在编译的语言的最严格的别名规则。对于C(和C++),这会激活基于表达式类型的优化。特别是,假设一种类型的对象永远不会与不同类型的对象位于同一地址,除非类型几乎相同。例如,无符号int可以别名为int,但不能别名为void*或double。字符类型可以别名为任何其他类型。

我错了,真丢脸。

 >:c

根据elaine的说法,finline小函数是问题的根源

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

使用构造reinterpret_cast<void *>(tp.tv_nsec),您将获取long并将其解释为指针。这导致错误的内存访问。您应该获取其地址并将其强制转换为void*:reinterpret_cast<void *>(&tp.tv_nsec)

答案是针对C的,但我认为针对C++的答案是类似的。从整数类型到指针的转换并不能保证在所有情况下都有效,因为它们可能具有不同的宽度,并且指针可能会被分段。如果有一个整数类型在您的平台上适用,那么它应该是typedef[u]intptr_t,所以如果您必须执行这种cruft,请使用该类型。

然后,您将mmap与一些根本无法预见的事情一起使用。如果你给它一个地址,你有责任验证这是你地址空间中的有效地址。例如,它必须是页面大小的倍数,但可能会有其他限制。检查mmap调用的返回值,看看它是否成功。

首先,最好阅读系统附带的文档。man mmap是你的朋友。