【问题标题】:Can I read any readable valid memory location via a (unsigned) char* in C++?我可以通过 C++ 中的(无符号)char* 读取任何可读的有效内存位置吗?
【发布时间】:2011-10-01 20:48:12
【问题描述】:

我的搜索 foo 今天似乎缺少。

我想知道根据标准 C++ 通过 (unsigned(?)) char* 检查“任何”内存位置是否合法any 位置是指程序内对象或数组(或数组内)的任何有效地址。

举例:

void passAnyObjectOrArrayOrSomethingElseValid(void* pObj) {
   unsigned char* pMemory = static_cast<unsigned char*>(pObj)
   MyTypeIdentifyier x = tryToFigureOutWhatThisIs(pMemory);
}

免责声明:这个问题纯粹是学术性的。我不打算把它放到生产代码中! legal 我的意思是如果根据标准它真的是legal,那就是它是否可以在所有实现中 100% 起作用。 (不只是在 x86 或一些常见的硬件上。)

子问题:static_cast 是从 void* 地址获取 char* 指针的正确工具吗?

【问题讨论】:

    标签: c++ string pointers void-pointers memory-access


    【解决方案1】:

    C++ 假定有严格的别名,这意味着两个根本不同类型的指针不会对相同的值进行别名。

    但是,正如 bdonlan 正确指出的那样,该标准对 charunsigned char 指针进行了例外处理。

    因此,对于任何指针类型读取任何有意的地址(可能是任何类型),通常这是未定义的行为,但对于unsigned char的特殊情况,如问题所示允许(ISO 14882:2003 3.10(15))。

    static_cast 会进行编译时类型检查,因此它不太可能总是有效。在这种情况下,您将需要reinterpret_cast

    【讨论】:

    • 这不是真的——任何想出更好主意的人都可以搜索reinterpret_cast——他们无法搜索 C 风格的演员表。此外,C 风格的强制转换可能会在没有警告的情况下变得更糟,例如 const_cast
    • 好点...能够文本搜索 reinterpret_cast 是一大优势,我从来没有想过这一点。
    • unsigned charchar 允许使用任何其他类型的别名;请参见 ISO/IEC 9899:1999 (E) §6.5/7,最后一个项目符号以及脚注 73。但是,将任意地址(即,不是从获取有效对象的地址派生的地址)传递给其他地址是未定义的行为原因(§6.5.6/8、§6.5.3.2/4 等)
    • 请注意,9899:1999 是 C99 规范,而不是 C++,但它可能是相同的,因为 C++ 在语义方面试图普遍兼容...
    • 你说得对,那就是 ISO 14882:2003 3.10(15),我会更新答案。
    【解决方案2】:

    根据 ISO/IEC 9899:1999 (E) §6.5/7:

    7. 对象的存储值只能由具有以下之一的左值表达式访问 以下类型:

    • 与对象的有效类型兼容的类型,
    • [...]
    • 一种字符类型

    因此,通过unsigned char 取消引用和检查(有效)指针是合法的(在 C 中)。但是,您将在那里找到的内容未指定; tryToFigureOutWhatThisIs 没有明确定义的方法来实际弄清楚它在看什么。我这里没有 C++ 规范的副本,但我怀疑它使用相同的定义,以保持兼容性。

    【讨论】:

    • C++ 有类似的语言:“a char or unsigned char type”而不是“a character type”
    【解决方案3】:

    您只能使用char*,而不是unsigned char*。使用unsigned char* 将打破严格的别名规则并调用未定义的行为,但char* 有一个例外。然而,试图用你读到的内存做任何事情是非常可疑的,而且很可能会做一些未定义的事情。这就是为什么它很少在惯用的 C++ 代码中完成。

    【讨论】:

    • 嗯,确定吗?我认为该异常也适用于 unsigned char。 (但不要以为我真的查过它)
    • @jalf:我很确定我看到了一个标准报价,它只写了char*
    • ISO/IEC 9899:1999 (E) §6.5/7 引用“字符类型”;这允许签名或未签名的访问。这不是 C++ 规范,但很可能是一样的......
    • 在 C++03 和 C++11 中肯定是 charunsigned char。显然,即使char 是有符号类型,signed char 也很糟糕。 C++03 中的 3.10 [basic.lval]/15,C++11 中的 3.10 [basic.lval]/10
    • @Dennis, @bdonlan:谢谢,非常有帮助。我问是因为我不确定,很高兴看到相关的标准报价。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多