我这样做是为了学习。我正在学习的C++书将缓冲区转换为便于操作和流的结构。在我尝试使用数组(body)并在赋值后查看缓冲区中的二进制数据之前,一切看起来都很好。不符合我的预期。
#include <iostream>
#include <bitset>
#include <netinet/in.h>
using namespace std;
struct dataStruct
{
uint32_t header;
uint32_t *body;
};
int main(int argc, char* argv[])
{
int size, streamSize;
// 4 bytes per size + 4 bytes for header
size = 1;
streamSize = (size * 4) + 4;
// Create a stream of bytes of appropriate size
uint8_t *buffer = new uint8_t[streamSize];
// Cast stream as structure
dataStruct *sStream = (dataStruct *)buffer;
// Populate structure with nice 101010... binary patterns
sStream->header = 2863311530;
sStream->body = new uint32_t[1];
sStream->body[0] = 2863311530;
cout << "Struct: " << sStream->header << ", " << sStream->body[0] << endl;
// Look at raw data in stream
for (int i=0; i<sizeof(buffer); i++)
{
std::bitset<8> x(buffer[i]);
cout << "[" << i << "]->" << x << endl;
}
return 0;
}产出如下:
Struct: 2863311530, 2863311530
[0]->10101010
[1]->10101010
[2]->10101010
[3]->10101010
[4]->00000000
[5]->00000000
[6]->00000000
[7]->00000000为什么索引4-7和0-3不一样?sStream->header和sStream->body都包含相同的值。它们被映射到缓冲区。这是因为身体是数组吗?如果是这样的话,当使用数组时,我将如何操作流以使其工作?
谢谢
发布于 2014-06-23 18:26:45
您正在使用未初始化的变量size:
streamSize = (size * 4) + 4;之后的一切都取决于streamSize,这是可疑的,也是导致未定义行为的原因。
更新
即使在size初始化为1之后,也会出现问题。让我们来看一看代码以及它如何影响您分配的内存。
在执行行之后:
uint8_t *buffer = new uint8_t[streamSize];buffer指向内存,如下所示:
buffer
|
v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+在您执行行之后:
dataStruct *sStream = (dataStruct *)buffer;sStream指向相同的内存,如下所示:
sStream
|
v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+如果您的编译器没有向dataStruct的成员添加任何填充(最好的情况场景),那么您将拥有:
sStream.header sStream.body
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+如果编译器将填充添加到dataStream.header中,则sStream.body将指向不同的内容。最坏的情况是:您有一个64位编译器。它在dataStream.header中增加了32位的填充。在这种情况下,您将拥有:
sStream.header sStream.body
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+然后,当您尝试将任何东西分配给sStream.body时,您将使用未使用的内存,例如:
sStream->body = new uint32_t[1];最好的情况是,您有32位编译器,并且没有添加到dataStream.header中的填充。看来你有64位编译器。即使您的编译器没有向dataStream.header添加任何填充,如果sizeof(void*)是64位的话,您仍然会看到内存溢出问题,我认为是这样的。
让我们以32位编译器为例,它不添加任何填充,sStream的成员指向分配的内存,如下所示:
sStream.header sStream.body
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+在执行行之后:
sStream->header = 2863311530;内存看起来像:
sStream.header sStream.body
| |
v v
+---+---+---+---+---+---+---+---+
| 2863311530 | |
+---+---+---+---+---+---+---+---+在执行行之后:
sStream->body = new uint32_t[1];内存看起来像:
sStream.header sStream.body
| |
v v
+---+---+---+---+---+---+---+---+
| 2863311530 | SomeMemory |
+---+---+---+---+---+---+---+---+
SomeMemory
|
v
+---+---+---+---+
| |
+---+---+---+---+在执行行之后:
sStream->body[0] = 2863311530;SomeMemory会被填充,如下所示:
SomeMemory
|
v
+---+---+---+---+
| 2863311530 |
+---+---+---+---+我认为您很惊讶地看到,buffer指出的内存看起来不像:
buffer
|
v
+---+---+---+---+---+---+---+---+
| 2863311530 | 2863311530 |
+---+---+---+---+---+---+---+---+我希望现在说得通,为什么不这样做。
https://stackoverflow.com/questions/24372555
复制相似问题