qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码

初识Qt,进行开发时遇到一个崩溃问题 简单整理

1:问题描述如下,结构体中QString成员,然后对结构体调用了memset导致问题:

在这里插入图片描述

2:问题分析,加断点调试的方式可以明确分析到行数

可以明确看出,初始化时成员变量的值为空的字符串,然后执行memset后,该成员地址无法访问。
在这里插入图片描述

3:找源码进行分析一下

3.1.这里首先测试一下string等其他成员操作,没有出现问题。

3.2 分析QString的源码,了解原因(qtbase源码分析)。

简化后源码如下

const QArrayData QArrayData::shared_null[2] = {{ -1, 0, 0, 0, sizeof(QArrayData) }, }
inline QString::QString() noexcept : d(Data::sharedNull()) {}
inline QString::~QString() { if (!d->ref.deref()) Data::deallocate(d); }class Q_CORE_EXPORT QString
{
public:typedef QStringData Data; //基类是 QArrayDatainline QString() noexcept;
private:Data *d; //基类是 QArrayData 控制引用计数
public:typedef Data * DataPtr;inline DataPtr &data_ptr() { return d; }
};QString::QString(const QChar *unicode, int size)
{if (!unicode) {d = Data::sharedNull();} else {if (size < 0) {size = 0;while (!unicode[size].isNull())++size;}if (!size) {d = Data::allocate(0);} else {d = Data::allocate(size + 1);Q_CHECK_PTR(d);d->size = size;memcpy(d->data(), unicode, size * sizeof(QChar));d->data()[size] = '\0';}}
}

第一个分析点(构造函数):
在这里插入图片描述

第二个分析点,真正控制QString的数据体,只能指针+数据域

实际真正的底层是QArrayData

struct Q_CORE_EXPORT QArrayData
{QtPrivate::RefCount ref; //基类实现原子变量的递增递减int size;uint alloc : 31;uint capacityReserved : 1;qptrdiff offset; // in bytes from beginning of headervoid *data() {Q_ASSERT(size == 0  || offset < 0 || size_t(offset) >= sizeof(QArrayData));return reinterpret_cast<char *>(this) + offset;}static const QArrayData shared_null[2];static QArrayData *sharedNull() noexcept { return const_cast<QArrayData*>(shared_null); }
};//真正的申请内存
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,size_t capacity, AllocationOptions options) noexcept
{Q_ASSERT(alignment >= Q_ALIGNOF(QArrayData)            && !(alignment & (alignment - 1)));if (!(options & RawData) && !capacity) {return const_cast<QArrayData *>(&qt_array_empty);}size_t headerSize = sizeof(QArrayData);if (!(options & RawData))headerSize += (alignment - Q_ALIGNOF(QArrayData));if (headerSize > size_t(MaxAllocSize))return nullptr;size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options);QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));if (header) {quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1)& ~(alignment - 1);header->ref.atomic.storeRelaxed(1);header->size = 0;header->alloc = capacity;header->capacityReserved = bool(options & CapacityReserved);header->offset = data - quintptr(header);}return header;
}//真正的释放内存 根据引用计数控制
void QArrayData::deallocate(QArrayData *data, size_t objectSize, size_t alignment) noexcept
{// Alignment is a power of twoQ_ASSERT(alignment >= Q_ALIGNOF(QArrayData)  && !(alignment & (alignment - 1)));Q_UNUSED(objectSize) Q_UNUSED(alignment)Q_ASSERT_X(data == 0 || !data->ref.isStatic(), "QArrayData::deallocate","Static data cannot be deleted");::free(data);
}

4:为什么string成员没有问题呢(分析QLatin1String)

这里在看QString源码时看到了QLatin1String类 区分QString进行了简单查看。

首先:QLatin1String作为结构体成员,也没有问题。
在这里插入图片描述

4.1 简单查看QLatin1String的源码

class QLatin1String
{
public:Q_DECL_CONSTEXPR inline QLatin1String() noexcept : m_size(0), m_data(nullptr) {}Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) noexcept : m_size(s ? int(strlen(s)) : 0), m_data(s) {}Q_DECL_CONSTEXPR explicit QLatin1String(const char *f, const char *l): QLatin1String(f, int(l - f)) {}Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) noexcept : m_size(sz), m_data(s) {}inline explicit QLatin1String(const QByteArray &s) noexcept : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}//。。。其他都是基本的函数接口Q_DECL_CONSTEXPR const char *latin1() const noexcept { return m_data; }Q_DECL_CONSTEXPR int size() const noexcept { return m_size; }Q_DECL_CONSTEXPR const char *data() const noexcept { return m_data; }Q_DECL_CONSTEXPR bool isNull() const noexcept { return !data(); }Q_DECL_CONSTEXPR bool isEmpty() const noexcept { return !size(); }private:int m_size;const char *m_data;
};

4.2 简单分析 QLatin1String 就是对char*的简单封装

在这里插入图片描述

4.2 细节,没看到有operator= 使用赋值构造也没有问题

这是因为用了浅拷贝,内部没涉及内存的重新申请 所以也没问题。

然后因为demo中x1重新赋值,浅拷贝导致x1中data指向的const char*指向发生变化。

总结:QLatin1String只是对char*的简单封装,不涉及内存的申请,实际还是需要我们控制。

遗留:过程中看到QString中相关的编码相关函数,这块也是一个细节,待整理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/46539.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows下问题定位

1、内存相关知识点&#xff1b; 1&#xff09;windows下32位进程&#xff0c;用户态为2G内存&#xff0c;内核态也为2G内存&#xff1b;却别于linux操作系统&#xff1b; 备注&#xff1a;可以通过命令行与管理员权限&#xff0c;启动3G的用户态空间&#xff0c;但是部…

Java 下载压缩zip

Java压缩zip /*** 下载压缩包** param instId 实例id* param response 响应* author 梁伟浩* date 2023-08-21*/GetMapping("/downloadZip")ApiOperation(value "下载压缩包")ApiImplicitParam(name "instId", value "实例id", r…

git权限问题解决方法Access denied fatal: Authentication failed

文章目录 遇到Access denied 的权限问题解决方法1、git的密码修改过&#xff0c;但是本地没更新。2、确定问题&#xff0c;然后增加配置① 查询用户信息②如果名称和email不对&#xff0c;设置名称&#xff1a;③ 检查ssh-add是否链接正常④ 设置不要每次都输入用户名密码 3、配…

6.小程序api分类

事件监听 以on开头&#xff0c;监听某个事件触发&#xff0c;例如&#xff1a;wx.WindowResize事件 同步 以Sync结尾的是同步&#xff0c;可以通过函数返回值直接获取&#xff0c;例如&#xff1a;wx.setStorageSync 异步 需要通过函数接收调用结果&#xff0c;例如&#…

mysql 数据类型

目录 数值类型 整数 tinyint 位类型 BIT(M) 浮点类型 float [(M, D)] [UNSIGNED] DECIMAL(M, D) [UNSIGNED] 二进制类型 字符型 CHAR(SIZE) VARCHAR(SIZE) 日期类型 DATE/DATETIME/TIMESTAMP string 类型 SET & ENUM 在前面的文章中&#xff0c;有时候茶树数…

【校招VIP】CSS校招考点之选择器优先级

考点介绍&#xff1a; 选择器是CSS的基础&#xff0c;也是校招中的高频考点&#xff0c;特别是复合选择器的执行优先级&#xff0c;同时也是实战中样式不生效的跟踪依据。 因为选择器的种类较多&#xff0c;很难直接记忆&#xff0c;可以考虑选择一个相对值&#xff0c;比如id类…

人大进仓数据库ksql命令基础

测试环境信息: 系统为银河麒麟V10 数据库为Kingbase ES V8 数据库安装目录为/opt/Kingbase/ES/V8 ksql命令位于/opt/Kingbase/ES/V8/Server/bin下 使用--help获取帮助 续上图 1.查看数据库列表 ./ksql -U system -l 2.查看数据库版本 ./ksql -V 3.连接指定的数据库tes…

如何写一个简单的dockerfile

Dockerfile 是一种文本文档&#xff0c;它包含了一组用户可以调用以创建镜像的指令。用户可以使用 docker build 命令&#xff0c;根据 Dockerfile 中定义的步骤&#xff0c;自动构建出一个新的 Docker 镜像。 以下是一些常用的 Dockerfile 指令&#xff1a; FROM&#xff1a…

python 条件编译如何写

在Python中&#xff0c;条件编译通常是通过预处理指令来实现的。与其他编程语言不同&#xff0c;Python没有像C或C那样的预处理器&#xff0c;但您可以使用一些技巧来模拟条件编译的效果。以下是一种在Python中模拟条件编译的常见方法&#xff1a; # 定义一个条件变量&#xf…

springboot使用mybatis配置多数据源

概述 配置多数据源有两种方案。一种是使用dynamic依赖的DS注解的方法&#xff0c;这种是比较简单方便的方法。另一种是本文介绍的方式&#xff0c;配置不同数据源的SqlSessionFactory 。 第二种方法是我在开发一个老项目时&#xff0c;老项目配置的方法。 application.xml s…

投资人热捧的创业大赛,有哪些AI原生应用值得关注?

“绝对远超全球同类产品”&#xff0c;一位大模型创业者对百度文心一言的表现不吝夸奖。 这是一家生产效率工具创业公司的负责人&#xff0c;今年5月百度发起大模型领域创业比赛——“文心杯”&#xff0c;他率先报名参赛并入选决赛文心创业营&#xff0c;目前与其他30多家入围…

【GAMES202】Real-Time Shadows2—实时阴影2

一、PCSS回顾 上一篇我们说了如何用PCSS是实现软阴影&#xff0c;这个过程是没有任何问题的&#xff0c;但是有一个速度的问题&#xff0c;因为PCSS涉及到非常多次对纹理特定某一块区域遍历的操作&#xff08;工业界一般都是用在该区域采样的方式&#xff0c;会因此产生噪声&am…

常见gis几何格式(wkt、geojson、arcgis json)的转换方法

1.相关链接 https://github.com/terraformer-js/terraformer 2.arcgis geometry json与geojson互转 Convert ArcGIS JSON geometries to GeoJSON geometries and vice versa. npm install terraformer/arcgis &#xff08;1&#xff09;arcgis geometry json转换成geojson格…

Zookeeper集群单节点启动成功但未同步其他节点数据

首先排查节点启动是否正常&#xff1a; 在zookeeper的bin目录下执行&#xff1a;sh zkServer.sh status 判断当前节点数据leader 还是follower 节点都启动正常&#xff0c;但某一个zookeeper集群节点&#xff08;下面简称“异常节点”&#xff09;不同步其他节点数据&#xf…

SQL-每日一题【1321. 餐馆营业额变化增长】

题目 表: Customer 你是餐馆的老板&#xff0c;现在你想分析一下可能的营业额变化增长&#xff08;每天至少有一位顾客&#xff09;。 计算以 7 天&#xff08;某日期 该日期前的 6 天&#xff09;为一个时间段的顾客消费平均值。average_amount 要 保留两位小数。 结果按 …

最新两年工作经验总结

最新两年工作经验总结 前言URP的使用1&#xff1a;如何开启URP1、老项目升级为URP2、创建新项目时选择URP创建 2&#xff1a;URP阴影的设置 PolyBrush的使用&#xff08;地图编辑插件&#xff09;制作山峰or低谷边缘柔化雨刷上色制造场景中的物体贴图地形创建容易踩坑的点ProBu…

飞天使-k8sv1.14二进制安装

文章目录 安装前准备安装前设置分发脚本 开始安装k8s集群cfssl 安装部署kubectl命令行工具创建admin证书和私钥创建kubeconfig文件部署ETCD集群部署Flannel网络kube-apiserver 高可用KeepLived 部署部署master节点部署高可用kube-controller-manager集群kube-controller-manage…

C++ namespace对全局变量屏蔽的工程化意义解读

namespace解决了什么&#xff1f; 解决了变量的跨域访问问题C解决了C语言不能访问全局变量的问题 #include<iostream> using namespace std;namespace glo{ int global 50; }int main(int argc, char *argv[]) {int global 20;std::cout << global << en…

java 工程管理系统源码+项目说明+功能描述+前后端分离 + 二次开发 em

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显…

【C++习题集】-- 堆

&#xff08;用于复习&#xff09; 目录 树概念及结构 名词概念 二叉树概念及结构 特殊的二叉树 满二叉树 完全二叉树 运算性质 二叉树存储结构 顺序存储 链式存储 堆 - 顺序存储 堆的性质 堆的实现 堆的应用 堆排序 直接建堆法 树概念及结构 概念&#xff1a…