首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >浇铸缓冲作为结构

浇铸缓冲作为结构
EN

Stack Overflow用户
提问于 2014-06-23 18:10:23
回答 1查看 185关注 0票数 2

我这样做是为了学习。我正在学习的C++书将缓冲区转换为便于操作和流的结构。在我尝试使用数组(body)并在赋值后查看缓冲区中的二进制数据之前,一切看起来都很好。不符合我的预期。

代码语言:javascript
复制
#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;
}

产出如下:

代码语言:javascript
复制
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都包含相同的值。它们被映射到缓冲区。这是因为身体是数组吗?如果是这样的话,当使用数组时,我将如何操作流以使其工作?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-23 18:26:45

您正在使用未初始化的变量size

代码语言:javascript
复制
streamSize = (size * 4) + 4;

之后的一切都取决于streamSize,这是可疑的,也是导致未定义行为的原因。

更新

即使在size初始化为1之后,也会出现问题。让我们来看一看代码以及它如何影响您分配的内存。

在执行行之后:

代码语言:javascript
复制
uint8_t *buffer = new uint8_t[streamSize];

buffer指向内存,如下所示:

代码语言:javascript
复制
buffer
|
v
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

在您执行行之后:

代码语言:javascript
复制
dataStruct *sStream = (dataStruct *)buffer;

sStream指向相同的内存,如下所示:

代码语言:javascript
复制
sStream
|
v
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

如果您的编译器没有向dataStruct的成员添加任何填充(最好的情况场景),那么您将拥有:

代码语言:javascript
复制
sStream.header  sStream.body
|               |
v               v
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

如果编译器将填充添加到dataStream.header中,则sStream.body将指向不同的内容。最坏的情况是:您有一个64位编译器。它在dataStream.header中增加了32位的填充。在这种情况下,您将拥有:

代码语言:javascript
复制
sStream.header                  sStream.body
|                               |
v                               v
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

然后,当您尝试将任何东西分配给sStream.body时,您将使用未使用的内存,例如:

代码语言:javascript
复制
sStream->body = new uint32_t[1];

最好的情况是,您有32位编译器,并且没有添加到dataStream.header中的填充。看来你有64位编译器。即使您的编译器没有向dataStream.header添加任何填充,如果sizeof(void*)是64位的话,您仍然会看到内存溢出问题,我认为是这样的。

让我们以32位编译器为例,它不添加任何填充,sStream的成员指向分配的内存,如下所示:

代码语言:javascript
复制
sStream.header  sStream.body
|               |
v               v
+---+---+---+---+---+---+---+---+
|   |   |   |   |   |   |   |   |
+---+---+---+---+---+---+---+---+

在执行行之后:

代码语言:javascript
复制
sStream->header = 2863311530;

内存看起来像:

代码语言:javascript
复制
sStream.header  sStream.body
|               |
v               v
+---+---+---+---+---+---+---+---+
| 2863311530    |               |
+---+---+---+---+---+---+---+---+

在执行行之后:

代码语言:javascript
复制
sStream->body = new uint32_t[1];

内存看起来像:

代码语言:javascript
复制
sStream.header  sStream.body
|               |
v               v
+---+---+---+---+---+---+---+---+
| 2863311530    |  SomeMemory   |
+---+---+---+---+---+---+---+---+

SomeMemory
|
v
+---+---+---+---+
|               |
+---+---+---+---+

在执行行之后:

代码语言:javascript
复制
sStream->body[0] = 2863311530;

SomeMemory会被填充,如下所示:

代码语言:javascript
复制
SomeMemory
|
v
+---+---+---+---+
| 2863311530    |
+---+---+---+---+

我认为您很惊讶地看到,buffer指出的内存看起来不像:

代码语言:javascript
复制
buffer
|
v
+---+---+---+---+---+---+---+---+
| 2863311530    | 2863311530    |
+---+---+---+---+---+---+---+---+

我希望现在说得通,为什么不这样做。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24372555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档