当前位置: 首页 > article >正文

QT将QBytearray的data()指针赋值给结构体指针变量后数据不正确的问题

1、问题代码

#include <QCoreApplication>

#pragma pack(push, 1)
typedef struct
{
    int a;		// 4字节
    float b;	// 4字节
    char c;		// 1字节
    int *d;		// 8字节
}testStruct;
#pragma pack(pop)

#include <QByteArray>
#include <QDebug>

int main()
{
    testStruct structA;

    structA.a = 1;
    structA.b = 2;
    structA.c = 'a';
    structA.d = new int[10];

    for (int i = 0; i < 10; ++i) {
        structA.d[i] = i;
    }

    QByteArray arr;

    arr.resize(49);

    memcpy(arr.data(), &structA, 9);

    memcpy(arr.data() + 9, structA.d, 40);
	
	testStruct *sb = reinterpret_cast<testStruct *>(arr.data());

    sb->d = reinterpret_cast<int *>(arr.data() + 9);

    for (int i = 0; i < 10; ++i) {
        qDebug() << sb->d[i];
    }

    return 0;
}

输出结果

40642209
0
2
3
4
5
6
7
8
9

2、调试过程1

经过调试指针转换后,发现本来设置的1字节对其变成了4字节对齐
QBytearray的data()指针被转换后会按照4字节自动对齐填充,不知为何会这样
在这里插入图片描述>在这里插入图片描述

3、调试过程2

当我采用系统默认的8字节对齐后,又发现无法正确的对结构体内指针进行赋值
下面这行代码,按理来说指针赋值,sb->d应该指向arr.data() + 16的地址上

typedef struct
{
    int a;		// 4字节
    float b;	// 4字节
    char c;		// 8字节
    int *d;		// 8字节
}testStruct;
sb->d = reinterpret_cast<int *>(arr.data() + 16);;

但实际上出现了一个奇怪的现象,在arr.data() + 16 的内存起始地址上,莫名填充了8个字节,而这8个字节恰好就是自己的内存地址??????
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其中00 00 00 00 00 f6 43 48 等于 16139080,输出的第一个值正好为自己的地址
由此得出,结构体指针的赋值会将值和地址一并一起赋值?匪夷所思

4、测试代码

测试一下,对于原始的char* c指针是否也有这样的情况

#include <QCoreApplication>

#pragma pack(push, 1)
typedef struct
{
    int a;
    float b;
    char c;
    int *d;
}testStruct;
#pragma pack(pop)

#include <QByteArray>
#include <QDebug>

int main()
{
    testStruct structA;

    structA.a = 1;
    structA.b = 2;
    structA.c = 'a';
    structA.d = new int[10];

    for (int i = 0; i < 10; ++i) {
        structA.d[i] = i;
    }

    QByteArray arr;

    arr.resize(49);

    memcpy(arr.data(), &structA, 9);

    memcpy(arr.data() + 9, structA.d, 40);

    testStruct *sb = reinterpret_cast<testStruct*>(arr.data());


    // 分配一片char数组,假设我们需要存储3个float

    char *charBuffer = new char[10 * sizeof(int)];

    // 假设填充一些数据
    int exampleData[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    memcpy(charBuffer, exampleData, 10 * sizeof(int));

    sb->d = reinterpret_cast<int*>(charBuffer);

    // (*sb).d = reinterpret_cast<int*>(arr.data() + 16);

    for (int i = 0; i < 10; ++i) {
        qDebug() << sb->d[i];
    }

    return 0;
}

输出正常,给我整得一头雾水

5、问题解析

最后思来想去,终于发现了问题所在
结构体指针sb->d和需要解析的数据块在同一块内存地址,地址空间重合了!!!

在给sb->d的值赋值时,其实就是修改sb->d所在内存空间的8个字节为新的地址0x12345678,但是这块地址又和自己的数据地址重合了,所以导致了数据地址的前8个字节被覆盖


http://www.kler.cn/a/327196.html

相关文章:

  • Brave编译指南2024 MacOS篇-构建与运行(六)
  • 正则表达式的使用规则
  • Linux —— Socket编程(三)
  • 深入理解 C++11 Lambda 表达式及其捕获列表
  • Lombok同时使⽤@Data和@Builder遇到的坑
  • 0基础学习PyTorch——监控机器学习的可视化工具
  • PostgreSQL 字段使用pglz压缩测试
  • OceanBase企业级分布式关系数据库
  • TypeScript 算法手册 - 【冒泡排序】
  • 海陆钻井自动化作业机器人比例阀放大器
  • Apache Solr:深入探索与常见误区解析
  • 深度学习实战:UNet模型的训练与测试详解
  • 关于 JVM 个人 NOTE
  • ARM Assembly: 第8课 branching
  • Web自动化中常用XPath定位方式
  • D23【 python 接口自动化学习】- python 基础之判断与循环
  • Docker入门指南:快速学习Docker的基本操作
  • 网络编程(13)——单例模式
  • BCJR算法——卷积码的最大后验译码
  • Ubuntu 开机自启动 .py / .sh 脚本,可通过脚本启动 roslaunch/roscore等