【问题标题】:Memory leak while writing out libjpeg image写出 libjpeg 图像时内存泄漏
【发布时间】:2020-09-21 14:53:17
【问题描述】:

我在一个自制的 C++ 框架中工作,其中一个类间接连接到 libjpeg-8c.so(作为 Ubuntu 16.04 突触包获得)。我在我的应用程序上运行 valgrind,最终会写出如下所示的图像数据:

        ImageDescriptor* pOutputImageDesc, int outputQuality)
{
   //set up JPEG lib context
    /* Step 4: Start compressor
     * true ensures that we will write a complete interchange-JPEG file.
     * Pass true unless you are very sure of what you're doing.
     */
    jpeg_start_compress(&cInfo, TRUE);

    /* Step 5: while (scan lines remain to be written)
     *           jpeg_write_scanlines(...);

     * Here we use the library's state variable cInfo.next_scanline as the
     * loop counter, so that we don't have to keep track ourselves.
     * To keep things simple, we pass one scanline per call; you can pass
     * more if you wish, though.
     */

    rowStride = pInputImageDesc->width * pInputImageDesc->channels; // JSAMPLEs per row in image_buffer

    while (cInfo.next_scanline < cInfo.image_height)
    {
        /* jpeg_write_scanlines expects an array of pointers to scanlines.
         * Here the array is only one element long, but you could pass
         * more than one scanline at a time if that's more convenient.
         */
        rowPointerArray[0] = &inputBuffer[(cInfo.next_scanline * (rowStride))];
        static_cast<void>(jpeg_write_scanlines(&cInfo, rowPointerArray, 1));
    }

    // Step 6: Finish compression
    jpeg_finish_compress(&cInfo);

    //setup external image context

    // Step 7: release JPEG compression object
    // This is an important step since it will release a good deal of memory.
    jpeg_destroy_compress(&cInfo);

    return 0;
}

与评论所说的相反,并非所有堆内存都被释放。 Valgrind 在这个 malloc() 跟踪中的想法不同

注意:下面的跟踪是在链接到 libjpeg-8d 源之后出现的

==6025==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6025==    by 0x4E4CDCE: empty_mem_output_buffer (jdatadst.c:131)
==6025==    by 0x4E4373E: dump_buffer_s (jchuff.c:274)
==6025==    by 0x4E4373E: emit_bits_s (jchuff.c:329)
==6025==    by 0x4E4373E: encode_one_block (jchuff.c:990)
==6025==    by 0x4E4373E: encode_mcu_huff (jchuff.c:1040)
==6025==    by 0x4E40DAB: compress_data (jccoefct.c:208)
==6025==    by 0x4E45B3F: process_data_simple_main (jcmainct.c:135)
==6025==    by 0x4E3EEE3: jpeg_write_scanlines (jcapistd.c:108)
==6025==    by 0x40DC4E: CompressRawToJpg(ImageDescriptor*, ImageDescriptor*, int) (ImageCaptureHelper.cpp:646)
==6025==    by 0x40DFB2: WriteJpgImage(char*, ImageDescriptor*) (ImageCaptureHelper.cpp:756)
==6025==    by 0x40CB18: Recognition::OutputImage::encode() (output_image.cpp:58)
==6025==    by 0x403AD4: main (testImgNorm.cpp:127)

所以,在查看了 mem_empty_output_buffer() 调用之后,我认为这个内存泄漏是由于:

1 - libjpeg-8c 写得不好(当然也不清楚这个 fct 和它的调用者接口如何,但我离题了);但是,考虑到这个库的广泛使用,我对此表示怀疑。

2 - CompressRawToJpeg() 应该在 *j_compress_ptr 中某处的 malloc'ed 缓冲区上调用 free()

3 - 这是 libjpeg 中的一个真正错误,我应该使用另一个库。

我希望遇到类似问题的人可以为我的代码提供一种写出 jpeg 图像的方法,而不会耗尽 64K 内存块(每个文件)。

谢谢,查尔斯

【问题讨论】:

  • 可能被this answer解决了?很难说,因为您没有包含所有与 jpeg 相关的代码。

标签: linux api memory-leaks libjpeg


【解决方案1】:

问题很可能是jpeg_mem_dest() 分配了自己的内存并忽略了您作为第二个参数提供的任何内容:

uint8_t* output = NULL;
unsigned long outputSize = 0;
jpeg_mem_dest(&cInfo, &output , &outputSize);

所以在编码过程结束时没有调用free() 时就会发生泄漏:

jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
free(output);

【讨论】:

    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多