我正在将数据缓冲区转换为大型结构指针。它会引起任何问题吗?我在 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/