【问题标题】:Accessing invalid memory via cast?通过强制转换访问无效内存?
【发布时间】:2015-01-14 12:00:55
【问题描述】:

举这个人为的例子:

#include <stdlib.h>
#include <string.h>

int main (int argc, char const *argv[])
{
    char *buf = malloc(8);
    strcpy(buf,"Hello W");

    char *last = &buf[4];

    size_t u = *(size_t *)(last);

    printf("0x%lx",u); // prints "0x57206f" on little endian

    return 0;
}

根据我对 C 的内存管理的(相当基本的)理解,这将导致以下内存读取(假设为 64 位):

+--+--+--+--+--+--+--+--+--+--+--+--+--+
|H |e |l |l |o |  |W |\0|? |? |? |? |… |
+--+--+--+--+--+--+--+--+--+--+--+--+--+
             ^^^^^^^^^^^^^^^^^^^^^^^

从而访问可能尚未分配给程序的内存区域并导致崩溃。 然而,这在实践中似乎工作得很好——这是定义的行为吗?

加法:

我根据此处显示的代码制作了这个示例:http://www.daemonology.net/blog/2008-06-05-faster-utf8-strlen.html

【问题讨论】:

  • size_t 的大小是多少?是 4 吗?
  • 请注意,*(size_t *)(last); 也会导致未定义的行为。存储在last 中的地址不是来自size_t 类型,并且很可能该地址也没有与size_t 类型正确对齐。
  • printf("0x%lx",u); 也有未定义的行为。 longsize_t 的大小可能不同。使用"0x%zx",u"0x%lx", (long)u
  • @Codor 如上所述,我假设标准 64 位平台的 sizeof(size_t)==8
  • Here 可能还有here,对于常见的strlen 实现基本相同。可能这里有更好的副本,搜索 strlen 可能有助于找到它们。

标签: c


【解决方案1】:

你的理解正在停止。

会发生未定义的行为。当然,发生这种情况时的确切可见结果是未定义的。您不能声称“它有效,因为它没有崩溃”。不崩溃当然是可能发生的一件事,但崩溃也是如此。毕竟,行为是未定义的。

【讨论】:

  • 是的,但这只是一个简短的示例。我从中获取的代码被大量使用,所以我假设是否真的有可能崩溃我现在已经看到了一个案例。
  • @dog 当然有可能发生崩溃,因为您正在做无效的事情并获得未定义的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-27
  • 2010-11-04
  • 1970-01-01
  • 2020-09-06
相关资源
最近更新 更多