C mmap分配返回0xFFFFFFFFFFF4(非映射失败)

C mmap分配返回0xFFFFFFFFFFF4(非映射失败),c,linux,mmap,errno,C,Linux,Mmap,Errno,我正在尝试使用mmap分配内存,下面是代码: long long *copy; copy = (long long*)mmap(NULL, (size_t)1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); if (copy == MAP_FAILED)

我正在尝试使用mmap分配内存,下面是代码:

long long *copy;
copy = (long long*)mmap(NULL,
                       (size_t)1024,
                        PROT_READ | PROT_WRITE | PROT_EXEC,
                        MAP_PRIVATE | MAP_ANON, -1, 0);

  if (copy == MAP_FAILED) {
    fprintf(stderr, "Memory allocation failed (Process aborted)\n");
    exit(1);
  }
  printf("Pointer: %p\n", copy);
显然,我会检查分配是否失败。当这种情况发生时,我应该从我收集的数据中得到-1。问题是我得到了-12,好的
0xfffffffffff4
,这样错误就不会被捕获,程序继续运行。我想这可能是因为
(long-long*)
强制转换,但是强制转换不应该改变指针值。所以我很好奇为什么会发生这种情况,以及如何预防它

更奇怪的行为:

我试图打印
errno
。如果我使用
printf(“%d\n”,errno)
它打印0,指针仍然设置为
0xfffffffffff4
。但是如果我使用
err(errno,“%p”,copy)然后打印:

program.exe: 0x7f8130981000: Success

现在指针是有效的,但我不能使用它,因为
err
终止了执行。

当编译时,所有警告(
-Wmissing-prototype-Wstrict-prototype-Werror-Wextra
),正如注释中建议的那样,我意识到
没有包括在内。当我把它包括进来时,我在问题末尾描述的“奇怪行为”消失了;程序运行正常,但指针仍然不正确,我不知道,但在这一点上,如果我不检查
errno
,程序就会工作

在代码的其他部分,我有汇编编写的函数,它们一直工作得很好(这就是为什么我认为错误与它们无关)。但是我记得有些人使用
%rbx
在他们之间传递信息,但碰巧的是
%rbx
是gcc中用于
errno
的寄存器

因此,查看为该函数生成的汇编代码,我意识到
%rbx
不受编译器的“保护”。添加到标题
修复了这一问题,现在一切正常


即使它似乎在没有适当的include的情况下工作,但这无疑是一个教训,需要更加小心,始终使用最大的警告选项。

您的问题很可能是
mmap
返回的演员。在C语言中,这是不必要的,并且可以隐藏bug。也许你忘了把
#包括在内?也许你还没有打开所有的警告
-Wall
可以告诉您更多。通过提供MCVE,您可能会得到更好的帮助:您是否尝试过使用
-Wmissing prototype-Wstrict prototype-Werror-Wextra
以及
-Wall
进行编译?同样,如果您已经包含了必要的标题,这不会改变任何事情-如果您是一个细心的编码者。如果您没有包含必要的标题,或者您是一个粗心的程序员,那么您可能要做的工作比您预期的要多。(我一直在使用这些选项;我没有机会成为一个粗心的程序员——至少,不会因为这些选项识别出的错误而遇到问题。)此外,如果使用
warnc()
而不是
err()
,会发生什么?我强烈建议使用原型选项——它可以防止此类问题。不包括
使其以不同的、更具创造性的方式失败-您不知道打印的指针
err()
是否有效,因为程序已退出。我没有经常看到像您看到的那样的行为(除了在proto-MCVE中),特别是当包含正确的头和声明函数时。在Linux(以及一些,也许许多其他系统)上,错误12是ENOMEM。是否存在使用有趣的映射函数将
-1
错误代码转换为
-errno
的危险?变得古怪…在linux上编译时,始终启用所有警告。至少使用:
gcc-c-ggdb-Wall-Wextra-pedantic-Wconversion-std=gnu11 myprogram.c-o myprogram.o
rbx
是一个被调用方保存的寄存器,如果您在手写程序集中使用它,您的工作就是保存和恢复它。在手工编写汇编程序之前,您应该知道这一点。问题是,现在已经包含了所有正确的头文件(并且汇编程序函数没有更改),它就可以工作了。我不知道为什么。我注意到,当包含正确的文件时,
%rsp
在调用
mmap()
之前又减少了几个字节,可能存在覆盖问题。