【发布时间】:2014-10-18 20:45:01
【问题描述】:
我一直在使用 LodePNG 的 lodepng_encode24_file 对一些 24 位 RGB 图像文件进行编码,到目前为止效果非常好。但是,我注意到当我为其提供大于 15360*15360 像素大小的数据集(14336*14336 像素图像编码良好)时,它似乎崩溃了。
可以通过简单地替换行来获得 32 位情况(崩溃前的最大大小略低)的这种行为的最小示例
unsigned width = 512, height = 512;
与
unsigned width = 1024*14, height = 1024*14;
在LodePNG's example_encode.c file 中,并执行它。
我之前遇到过 C 代码崩溃的问题,因为我将大型数组分配给堆栈内存(其最大大小通常在 2MB 左右)而不是堆内存,所以作为 C 的新用户,我的第一反应是看看是否堆内存大小有上限。
但是,according to this answer,堆内存没有限制,所以肯定有其他问题。
我的第二个猜测是,崩溃是由于 PNG 格式本身支持的最大图像尺寸的固有限制。但是,according to this answer 及其下方的注释,PNG 支持的最大文件大小约为 4,000,000,000 * 4,000,000,000 像素,所以这也不是罪魁祸首。
有没有人猜测可能出了什么问题?其他人在尝试时能够重现此错误吗?
编辑:就 RAM 消耗而言,我有 8GB RAM,减去硬件保留、使用中、修改和待机内存(Windows 资源监视器实用程序使用的术语)我进行计算时有大约 4GB 的可用 RAM。对于 15000*15000 大小的 32 位图像,需要的空间小于 1GB。同样,当我成功编码 14000*14000 24 位图像时,我的可用 RAM 在编码过程的任何时候都不会低于 3GB,所以我认为 RAM 用完不是问题。
【问题讨论】:
-
当然堆内存是有限制的,事实上有几个。首先是您的系统可以处理的限制,例如 32 位系统最多只能寻址 4GB。然后是系统可用的实际物理和交换空间量,减去操作系统所需的内存以及系统上运行的所有其他进程。最后,有一个限制,当你分配内存时,它必须是一个大的连续块,如果没有这么大的块可用,则分配失败。
-
根据您生成图像的方式,您可能希望每行对其进行编码 - 这样您只需要在内存中有一行。 PNG 格式对此很简单(撇开隔行扫描的 PNG),而 libpng 允许该模式或写入(和读取),请参见例如png_write_row()。 (我在我的 Java 库 PNGJ 中做同样的事情)。我不知道 LodePNG。
-
似乎是内存碎片问题,或 LodePNG 实现限制/错误。刚刚尝试使用 libpng 保存 16384x16384 24 位图像,工作正常。
-
@user2802841:你没有使用 LodePNG,是吗?
-
我强烈认为观察到的行为是 LodePNG 中的错误。我刚刚编译了当前版本,按照 OP 创建了示例程序并运行它。它确实崩溃了。在 Valgrind 下运行它揭示了 LodePNG 代码中的内存问题。