微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

0x0地址0xdeadbeef是什么意思?

我刚刚在代码中看到以下行:

#define ERR_FATAL( str,a,b,c ) {while(1) {*(unsigned int *)0 = 0xdeadbeef;} }

我知道0xdeadbeef意味着错误,但是当它在地址0时,这个值是什么意思呢? 0代表什么地址?

共享内存中的单个生产者/消费者环形缓冲区

我可以使用SetwindowPos将窗口放在另一个窗口后面,但是如何将它放在给定窗口的前面?

一个gui编辑器

io_submit()阻塞,直到前一个操作完成

以编程方式获取networking链接types和速度

地址0x0被编译器识别为一个NULL指针,并将成为一个实现定义的无效内存地址 ,在某些系统上完全是在系统内存的第一个可寻址位置,但在其他地方,它只是代码中的占位符一些通用的无效内存地址。 从C代码的角度来看,我们不知道将会是什么地址,只是访问它是无效的。 基本上这个代码片段试图做的是写入一个“非法的”内存地址,值为0xdeadbeef。 价值本身就是一些十六进制的拼写“死牛肉”,因此表明该程序是死牛肉(即一个问题),如果你不是一个母语为英语的人,我可以看到这可能不那么明确:)。 我们的想法是,这将触发分段错误或类似的情况,目的是通过在没有执行清理或其他操作(宏名称ERR_FATAL提示)的情况下立即终止程序来通知您存在问题。 大多数操作系统不让程序直接访问系统中的所有内存,代码假定操作系统不会让你直接访问位于地址0x0的内存。 鉴于你用linux标签标记了这个问题,这是你将看到的行为(因为linux不允许访问该内存地址)。 请注意,如果您正在处理类似嵌入式系统的问题,那么这可能会导致一堆问题,因为您可能会覆盖重要的东西。

请注意,将会有更好的方法来报告问题,而不是依赖于某些类型的未定义的行为导致某些副作用。 使用像assert这样的东西可能是一个更好的选择。 如果您想要使用abort()来终止程序,那么在标准库中它是一个更好的选择,并且正是您想要的。 查看来自ComicSansMS的答案,了解更多为什么这是更可取的。

把这个值(或者这个值的任何值)放在地址0中应该立即终止程序。

致命错误表示错误情况非常严重,以至于程序无法安全地继续执行而没有进一步的数据损坏风险。

特别是,没有待执行的清除操作将被执行,因为它们可能具有不期望的效果。 想一想将缓冲区中的数据损坏刷新到文件系统。 相反,该程序将立即终止,并允许通过核心转储或附加的调试器进一步检查情况。

请注意,C已经为此提供了一个标准库函数: abort() 。 呼叫abort对于这个目的是更可取的,其原因如下:

写入地址0不保证终止程序。 这不必要地限制了代码的可移植性,并且在代码实际上被重新编译并在写入地址0的平台上执行时导致实际的存储器存储操作时可能具有毁灭性的后果。

调用abort()对于阅读代码的人来说更容易理解。 你的问题证明,许多开发人员不明白代码是应该做什么的。 虽然宏的名字和价值deadbeef给了一些暗示,但它仍然是不必要的晦涩难懂。 另外请注意,在调试器中查看反汇编代码时,宏的名称将不可见。

更清楚地调用abort()信号意图。 这不仅对于代码本身是正确的,对于二进制文件的可观察行为也是如此。 假设这个操作在Unix机器上按预期执行,结果会得到一个SIGSEGV ,这是一个表示内存损坏的信号。 另一方面, abort()会引起SIGABRT ,表示程序异常终止。 除非致命错误的原因确实是内存损坏,否则在这种情况下抛出SIGSEGV掩盖程序失败的原因,并可能误导开发人员试图追捕错误。 当你认为信号可能不被调试器捕获时,这是特别微妙的,但是通过一个自动信号处理器,可能会调用不合适的代码进行错误处理。

因此,如果宏的唯一意图是发出一个致命的错误(顾名思义),调用abort将是一个更好的实现。

解引用一个无效的指针(这是上面的代码试图做)导致未定义的行为。 因为这个系统可以做任何事情 – 它可能会崩溃,它什么都不能做,或者恶魔可以飞出你的鼻子 。 这个页面是关于每个C程序员应该知道的有关未定义行为的很好的一页。

因此上面的代码是导致崩溃的错误方法。 正如comenter指出的那样,最好调用abort()。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐