c++ - 类型转换具有较大尺寸结构的缓冲区

标签 c++ casting

我正在将数据缓冲区转换为大型结构指针。它会引起任何问题吗?我在 Visual Studio 上尝试了以下代码,没有发现任何警告或错误。

#include <iostream>
using namespace std;

struct test
{
    char var1;
    char var2;
    long var3;
};
void function(char* data);

int main (void)
{
    char data[5] = {1, 0, 0, 3, 4};
    function(data);

    system("Pause");
    return 0;
}

void function(char* data)
{
    test* pTest = reinterpret_cast<test*>(data); // casting
    printf("%x\n", pTest->var1);
    printf("%x\n", pTest->var2);
    printf("%x\n", pTest->var3);
}

最佳答案

您必须了解内存管理的工作原理。您静态地分配了数组 data,因此它将被放在堆栈上(堆栈包含具有被调用函数的局部变量的帧)。堆栈是为每个进程静态分配的(这意味着,在整个进程的生命周期中,它具有恒定的大小)。

从现在开始,堆栈看起来像这样:

data[1, 0, 0, 3, 4]

现在您调用了函数 function。新的框架被放在堆栈上,所以它看起来像这样:

data[1, 0, 0, 3, 4] | return-pointer[a b c d] pTest [e f a b]
(main data)           (function data)

现在,您将数据转换为您的类型,其大小至少为 6 个字节(假设它可能需要 8 个或更多字节,具体取决于类内容对齐方式)。所以你尝试访问这些字节:

data[1, 0, 0, 3, 4] | return-pointer[a b c d] pTest [e f a b]
(main data)           (function data)
     *  *  *  *  *                   *

(请注意,我对堆栈的可视化进行了简化,调用该函数后可能还剩下更多数据)。

您在稍后的 printf 期间访问的所有内存都属于您的应用程序,因此操作系统不会引发访问冲突错误。您读取了数据,因此您不会损坏任何东西。但现在假设,您将向 pTest->var3 写入一些内容。这些字节将被覆盖:

data[1, 0, 0, 3, 4] | return-pointer[a b c d] pTest [e f a b]
(main data)           (function data)
     *  *  #  #  #                   #

现在看,您刚刚损坏了返回指针 - 您的程序很可能会在尝试退出 function 并返回 main 时崩溃。

通常,强烈建议只转换兼容的数据类型(大小相同)。编译器通常无法知道您的转换是否有效(特别是,如果您在转换过程中将指针转换为 void *)。因此,您应该非常小心地在程序中进行转换。

关于c++ - 类型转换具有较大尺寸结构的缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16602291/

相关文章:

c++ - Xcode - 包太大

c# - 在运行时将对象转换为字符串数组

c++ - 编译 C 代码时出现 ISO C++ 错误

c++ - 在构造函数中初始化成员

c++ - 当 QMenu 的 QAction 之一未触发时,防止 QMenu 关闭

c++ - 对错误的 undefined reference 显示了我的函数 GTKMM C++ 的额外参数

C#:枚举是否在上下文中适本地将自己转换为字符串或整数

c - 是否可以分配具有强制转换前缀的变量? (在宏内)

c++ - 无效转换导致的堆损坏?

java - 将 A<X,Y> 类型转换为 A<Object,Object>