【问题标题】:What is "(void*)-1" in the context of sbrk's return value?sbrk 的返回值上下文中的“(void*)-1”是什么?
【发布时间】:2020-06-20 09:41:37
【问题描述】:

sbrk()Linux Man Page 声明失败时返回 (void*) -1。什么是(void*) -1,它有什么意义吗?或者它只是一个实际上不可能是void* 的数字,它被转换为void*,只是为了满足返回void* 的函数签名?我问这个是因为我以前从未见过指向负地址的指针。我不知道这可以在任何平台上取消引用。

【问题讨论】:

标签: c linux


【解决方案1】:

正如您所猜想的,这只是一种返回神奇值-1 的方法。它被强制转换为一个指针,只是为了匹配函数签名。调用者将知道如何解释这个神奇的值,而不是试图取消引用它。

在内部,这实际上只是变为0xFFFFFFFFFFFFFFFF(或0xFFFFFFFF 用于32 位)。 可能有平台可以实际访问此地址,但这不是这里的目的。

【讨论】:

    【解决方案2】:

    在大多数操作系统中,内存是在一组页面中分配的(这些页面可以在物理 RAM 中,也可以是存储在永久存储磁盘/设备上的虚拟页面,每个页面通常为 4KB)。由于 -1(无符号 0xFFFFFFFFFFFFFFFF 或 0xFFFFFFFF 用于 32 位)是 QWORD(或 32 位 DWORD)的最大可能值,因此页面通常不能从该地址开始,因为它是地址空间中的最后一个地址。因此,-1 是一个很好的值来指示内存分配中的错误,因为它通常被认为是不存在的页面。至于指向负地址的指针,如果您曾经有过汇编经验,您的编译器负责在其代码生成中强制执行符号,您会记得一个变量没有隐含的符号(只有指令给它这个属性)。当您在汇编中访问内存区域时,地址被认为是无符号数。

    【讨论】:

    • 页面通常不能从“-1”开始,因为它是最大的地址的推理是似是而非的。操作系统和程序不需要按顺序分配内存。人类设计方案来组织记忆。例如,我们可以将内存分成一部分供用户程序使用,一部分供系统使用。其中,我们可能从“底部”(低编号地址)开始,说空间将用于数据,然后在“顶部”留出其他空间用于堆栈,在中间留出一些空间用于各种目的, 等等。所以“顶部”很可能被映射。
    • 顶部可以被映射,但内存页从 0xFFFFFFFF 开始是不明智的,因为在此之后没有更多空间。当然,您可以使用段偏移内存样式并设置虚拟地址方案以使页面从 0xFFFFFFFF 开始,但是为什么在 sbrk 中使用此值的一般概念实际上可能是特定于 linux 的!我不确定 linux 内核如何设置它的内存(windows 倾向于分散,而我相信 linux 不那么碎片化)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2017-12-03
    • 2019-10-08
    • 1970-01-01
    • 2014-04-15
    • 2019-11-19
    相关资源
    最近更新 更多