首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何防止Qt提供的Zlib的平减端(&compr_str)函数在应用程序构建时在windows上使用混合方式进行分段错误处理?

如何防止Qt提供的Zlib的平减端(&compr_str)函数在应用程序构建时在windows上使用混合方式进行分段错误处理?
EN

Stack Overflow用户
提问于 2020-10-22 13:33:50
回答 1查看 207关注 0票数 0

引言

我在代码中使用下面的代码进行Gzip压缩,并在非常特定的条件下体验代码分段错误。我试着自己解决这个问题后,基本上完全迷失了方向。

代码是由以下配置生成的:

  1. Linux x86-64 Ubuntu 18.04,Qt 5.12.7从源代码构建,使用系统zlib.
  2. Linux arm x86-64 Yocto,Qt 5.12.7从源代码构建,使用系统zlib .
  3. MSVC2017 64位,Qt 5.12.7来自正式安装程序,使用自构建的zlib Qt,因为没有从官方安装程序中为MSVC
  4. Windows x86-64,Qt 5.12.7提供一个,使用已交付的zlib

在配置1-3中,对压缩代码的测试调用成功.在配置4中,当从Qt创建者IDE中启动时,对压缩代码的测试调用就会成功。在配置4中,当从Power命令行生成时,对压缩代码的测试调用会导致一个分段错误,如: 1.在power中设置与Qt使用的环境变量相同的environment.ACLineStatus 2。调用与Qt中为MinGw-x86-64配置配置的Qt中配置的完全相同的命令。

当我试图为MSVC和MinGw使用32768的缓冲区大小时,即使在qt创建者内部调用测试时,我也可以在该特定行再现类似的崩溃。MSVC以16384崩溃,MinGw崩溃为32768,因此在我的代码中为缓冲区大小提供了下面的#ifdef

问题

  • 下面的实际压缩代码一般看起来还好吗?它最初不是由我编写的,我还没有详细了解如何正确使用zlib,但是,在ZLIB中,许多示例代码看起来像similar.
  • What可能会导致崩溃,其中他们的文档声明:“库不应该崩溃,即使在输入损坏的情况下”?
  • ,当我使用与qt创建者内部相同的构建环境变量从mingw32构建应用程序时,发生分段错误的原因是什么?

我做了混合构建(在IDE中调用测试表单的QT创建者构建,以及从命令行调用测试的手动cli构建),以便在只安装了QT的干净虚拟机上测试行为,在启动任何构建之前具有完全相同和干净的环境。

分段错误的代码

代码语言:javascript
复制
#define BASE2_ZLIB_WINDOWSIZE 15
#define GZIP_ZLIB_WINDOWSIZE (16 + BASE2_ZLIB_WINDOWSIZE)
#define MOD_GZIP_ZLIB_CFACTOR 9
#define MOD_GZIP_ZLIB_BSIZE 8096

#ifdef _MSC_VER
#define COMPR_BUFFER_SIZE 32768
#else
#define COMPR_BUFFER_SIZE 16384
#endif

QByteArray gzipCompress(QByteArray data, int compressionlevel)
{
    char buffer[COMPR_BUFFER_SIZE];

    z_stream cmpr_stream;
    cmpr_stream.next_in = reinterpret_cast<unsigned char *>(data.data());
    cmpr_stream.avail_in = static_cast<uInt>(data.size());
    cmpr_stream.total_in = 0;
    cmpr_stream.total_out = 0;

    cmpr_stream.zalloc = Z_NULL;
    cmpr_stream.zalloc = Z_NULL;

    QByteArray compressed;

    // the actual compression work.
    if (deflateInit2(&cmpr_stream, compressionlevel, Z_DEFLATED, GZIP_ZLIB_WINDOWSIZE, MOD_GZIP_ZLIB_CFACTOR,
                        Z_DEFAULT_STRATEGY) != Z_OK)
    {
        return compressed;
    }
    // retrieve the compressed bytes blockwise
    int ret;
    do
    {
        cmpr_stream.next_out = reinterpret_cast<uint8_t *>(buffer);
        cmpr_stream.avail_out = COMPR_BUFFER_SIZE;
        ret = deflate(&cmpr_stream, Z_FINISH);

        if (static_cast<unsigned long>(compressed.size()) < cmpr_stream.total_out)
        {
            // append the block to the output string
            compressed.append(buffer, static_cast<int>(cmpr_stream.total_out) - compressed.size());
        }
    } while (ret == Z_OK);

    deflateEnd(&cmpr_stream);

    if (ret != Z_STREAM_END)
    {
        return QByteArray();
    }
    return compressed;
}

测试,调用代码

代码语言:javascript
复制
TEST(Compression, gzipSuccessfull)
{
    QString string_data(
        "Complex Test 256/n Data complete Lorem ipsum dolor sit amet, consetetur sadipscing elitr "
        "Lorem ipsum dolor sit amet, consetetur sadipscing elitr");
    QByteArray raw = string_data.toLatin1();
    qDebug() << "Orig size: " << raw.size();
    // Crashes in the next line
    QByteArray compressed = gzipCompress(raw);
    qDebug() << "Compressed size: " << compressed.size();
    QByteArray uncompressed = gzipDecompress(compressed);
    qDebug() << "Uncompressed size: " << uncompressed.size();
    QString restored = QString::fromLatin1(uncompressed);
    ASSERT_TRUE(string_data == restored);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-22 15:39:03

不确定这是否是导致分段错误的原因,但您需要初始化zfree。它看起来像是代码中的复制/粘贴错误,因为您已经初始化了两次zalloc。应:

代码语言:javascript
复制
cmpr_stream.zalloc = Z_NULL;
cmpr_stream.zfree = Z_NULL;

并完成:

代码语言:javascript
复制
cmpr_stream.opaque = Z_NULL;

关于附加多少的计算看起来是正确的,但这是一种迂回的方法,如果long为32位,则可能会出现可移植性问题。在这种情况下,当超过4GB时,total_out不会表示出总数。相反,您应该直接使用deflate()的结果

代码语言:javascript
复制
    if (cmpr_stream.avail_out < COMPR_BUFFER_SIZE)
    {
        // append the block to the output string
        compressed.append(buffer, COMPR_BUFFER_SIZE - cmpr_stream.avail_out);
    }

由于append的参数是int而不是unsigned,所以您应该确保COMPR_BUFFER_SIZE适合于int

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

https://stackoverflow.com/questions/64483407

复制
相关文章

相似问题

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