c++ - 类型转换时如何分配内存?

标签 c++

我们可以通过将连续的内存块转换为对象来创建对象。如果我们创建一个内存很少的对象,它在访问它时不会崩溃。但是它在超出范围时崩溃了。为什么?

class A
{
    public:
        int i;
};
void main(int argc, char * argv[])
{
    {
        vector<BYTE> v(1);
        A* a = (A*)v.data();
        a->i = 70000;          // a's memory can't hold 4 bytes (int). Why no crash?
        cout << a->i << endl;  // Printed value - 70000. Why not crash here
    }                          // Crashed here with heap corruption detected
    cout << "End of scope\n";
}

最佳答案

从正式的角度来看,您只是在调用未定义行为,因为您正试图将 BYTE * 作为 A * 进行访问。根据严格的别名规则,编译器可以做任何它想做的事。

在现实世界中,这将取决于实现,并且很可能会给出正确的结果。在幕后,vector 的常见实现为其 data 成员使用分配的内存。这意味着:

  • 它将针对任何类型正确对齐
  • 实际分配的内存可能至少足够一个 int(由于对齐,它在 32 位系统上至少有 4 个字节,在 64 位系统上至少有 8 个字节)
  • 您可以安全地更改分配内存的类型

这意味着这段代码不会崩溃也就不足为奇了,即使它是普通的未定义行为。

注意:除非在非常特殊的情况,并且有红色闪烁字体的通知,否则您不应该依赖代码的实现细节,因为它可能会在下一个版本的编译器中崩溃,或者只是如果您更改构建选项。

堆损坏只是一个警告,因为您的实现在它提供给您的最后一个字节之后放置了一个标记,并且发现该标记已被覆盖。但是从低层次的角度来看,你没有删除任何重要的东西——假设你的实现就像我的一样:-)

关于c++ - 类型转换时如何分配内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39245756/

相关文章:

c++ - 如何在JNI中将java异常作为jobobject抛出

c++ - 使用 QT Phonon 立即播放声音(不等待事件循环)

c++ - 这种字符串格式在 C++ 中意味着什么?

c++ - 如何安全、明智地确定指针是否指向指定缓冲区的某处?

c++ - Boost Log Formatter 使用与关键字相同的字符串

android - SimpleJSON C++ 类无法在 Android (NDK) 上解析字符串,但同一类在所有其他平台上都有效

c++ - golang 的 Swig 包装器

c++ - 有没有办法为 std::map 中小于给定键的第一个元素找到反向迭代器?

c++ - 如果文件/目录大小增加到配置级别以上,有没有办法在 linux 中回调

c++ - 检查一个序列是否由两个相同的序列组成