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

这篇具有很好参考价值的文章主要介绍了qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码,qt相关问题及学习,qt,开发语言

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

可以明确看出,初始化时成员变量的值为空的字符串,然后执行memset后,该成员地址无法访问。
qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码,qt相关问题及学习,qt,开发语言

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; //基类是 QArrayData
    inline 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';
        }
    }
}

第一个分析点(构造函数):
qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码,qt相关问题及学习,qt,开发语言

第二个分析点,真正控制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 header
    void *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 two
    Q_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作为结构体成员,也没有问题。
qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码,qt相关问题及学习,qt,开发语言

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*的简单封装

qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码,qt相关问题及学习,qt,开发语言

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

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

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

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

遗留:过程中看到QString中相关的编码相关函数,这块也是一个细节,待整理文章来源地址https://www.toymoban.com/news/detail-655013.html

到了这里,关于qt初入门0:结构体中QString用memset导致崩溃分析及QLatin1String简单查看源码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT--崩溃原因分析

    本文为学习记录,若有错误,请联系作者,谦虚受教。 你从来来去自由,若你不想要了跑开便是。 发布的客户版本里分析崩溃原因,便于解决问题。 在自己QT安装的目录下,例如:D:QtQt5.12.3Toolsmingw730_32bin,找到adde2line.exe。 将add2line.exe复制到自己发布的版本中。 在代码

    2024年02月13日
    浏览(62)
  • qt软件崩溃的分析方法-定位源文件和行号

    软件(debug版exe或者release版exe)在正常运行状态下(不是gdb调试运行),如果软件崩掉,那么会直接闪退,软件什么也做不了,此时无法保存软件中的状态信息,此外,也无法提供任何软件崩溃原因的信息。因此,软件崩掉,我们需要能给出信息才行,指导我们修改源码。解

    2024年02月07日
    浏览(46)
  • Qt QByteArray如何转QString

    要将QByteArray转换为QString,可以使用QString的构造函数或QString的fromUtf8()方法。 以下是两种常用的方法: 1. 使用QString的构造函数: ```cpp QByteArray byteArray = \\\"Hello World\\\"; QString str(byteArray); ``` 2. 使用QString的fromUtf8()方法: ```cpp QByteArray byteArray = \\\"Hello World\\\"; QString str = QString::fromUtf8(

    2024年01月19日
    浏览(38)
  • rust学习-打印结构体中的vec

    将格式化后的数据写入到一个缓冲区(buffer),而不是直接打印到标准输出或文件中。 这个缓冲区可以是字符串,也可以是需要写入的文件的缓冲区。 writer 参数是一个实现了 std::io::Write trait 的对象,表示要将数据写入到哪里。 format_string 是一个格式化字符串,可以包含占位

    2024年02月12日
    浏览(40)
  • 取个对象值导致系统崩溃

    想必各位小伙经常在项目中遇到一些错误,取 对象值的时候 ,经常 报错 ,又或者某些项目突然就 挂 经常都是出现在一些 对象取值上面 ,然后就被领导一顿训斥 例如: 下面这个报错大家想必不会陌生, 就是读取不存在对象的变量 那么为什么我们会遇到这个问题呢? 下面

    2024年02月13日
    浏览(37)
  • C++ Qt开发:字符串QString容器

    在Qt框架中, QString 是一个强大而灵活的字符串容器,专为处理 Unicode 字符而设计。它提供了许多方便的方法来操作和处理字符串,使得在跨平台开发中能够轻松地进行文本操作。QString 是 Qt 开发中不可或缺的一部分,它的灵活性和强大的功能使其成为处理文本和字符串操作

    2024年02月05日
    浏览(56)
  • 【Qt5】QString的成员函数chop

    2024年1月19日,周五下午 QString 的 chop 方法用于从字符串的末尾移除指定数量的字符。这个方法会修改原始字符串,并返回 void。 下面是一个简单的示例: 在这个示例中,originalString 包含字符串 \\\"Chop me!\\\"。通过调用 chop(2) 方法,从字符串的末尾移除了两个字符,修改了原始字符

    2024年01月20日
    浏览(48)
  • 【Qt5】QString的成员函数trimmed

    2024年1月19日,周五下午 QString 的 trimmed 方法是用于移除字符串两端的空白字符(空格、制表符、换行符等)的方法。它返回一个新的字符串,该字符串是原始字符串去除两端空白后的结果。 下面是一个简单的示例: 在这个示例中,originalString 包含前后有空格的字符串。通过

    2024年01月20日
    浏览(45)
  • 如何根据结构体中成员的地址获取整个结构体的首地址

    根据结构体成员地址,获取整个结构体的首地址,在Linux系统、鸿蒙lite os操作系统中是一个很重要的功能。 在Linux系统中是通过container_of宏函数实现的 container_of通过结构体内某个成员的地址和该成员的名字,以及结构体类型,找到该结构体变量的首地址。 在鸿蒙Lite os中是通

    2024年02月11日
    浏览(42)
  • 【Qt】QString怎么判断是否含有某个字符串

    2023年10月29日,周日晚上 QString怎么判断是否含有某一字符串? 比如我想知道QString中是否含有\\\"connectToHost error\\\" 要判断一个 QString 是否包含特定的子字符串,可以使用  QString  类的  contains()  方法。 下面是使用  contains()  方法来判断一个 QString 是否包含特定子字符串的示例

    2024年02月06日
    浏览(86)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包