You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win10x64平台调用png_read_png后printf无输出问题求助

调用libpng的png_read_png后程序停止执行,printf无输出

环境信息

  • 平台:Win10 x64
  • 编译器:GCC
  • 语言:C
  • 依赖库:libpng16.dll

问题描述

调用png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);之后,后续的printf完全没有输出,程序卡在这一步或直接终止。已经尝试在printf末尾加换行,也手动调用了fflush(stdout),但都无效。

原始代码

#include <stdio.h>
#include <png.h>

int main(int argc, char* argv[])
{
  printf("starting...\n");
  
  FILE *fp = fopen("test.png", "rb");
  if (!fp) {
    printf("error #%d\n", 1);
  }  

  // Read the PNG header
  png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (!png_ptr) {
    printf("error #%d\n", 2);
  }

  // create stuct for png info/meta data
  png_infop info_ptr = png_create_info_struct(png_ptr);
  
  if (!info_ptr) {
    printf("error #%d\n", 3);
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    printf("error #%d\n", 4);
  }    

  png_init_io(png_ptr, fp);

  // Read the PNG image data
  printf("before printf dies\n");
  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  printf("this will not print after png_read_png is ran\n");
  fflush(stdout);

/* it won't print regardless if the below cleanup code is commented out or not */

  // Get the image dimensions and bit depth
  png_uint_32 width, height;
  int bit_depth, color_type;
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);


  // Allocate memory for the image data
  png_bytep *row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep));
  for (png_uint_32 i = 0; i < height; i++)
  {
      row_pointers[i] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
  }

  // Read the image data into memory
  png_read_image(png_ptr, row_pointers);

  // Clean up
  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  
  // Free the memory allocated for the image data
  for (png_uint_32 i = 0; i < height; i++)
  {
      png_free(png_ptr, row_pointers[i]);
  }
  png_free(png_ptr, row_pointers);
/**/

  fclose(fp);
  
    return 0;
}

程序输出

starting...
before printf dies

问题原因与修复方案

核心问题

  1. libpng的错误跳转机制:libpng用setjmp/longjmp处理错误,当png_read_png执行出错时,会直接跳转到之前setjmp的位置,不会执行后续代码。你的错误分支只打印了错误,没有终止程序或清理资源,导致程序继续执行异常代码。
  2. 重复读取操作:png_read_png已经完成了图像数据的读取,后续又调用png_read_image属于重复读取,会触发错误。
  3. 资源错误未及时终止:文件打开、结构创建失败时,只是打印错误却继续执行,导致后续操作使用无效指针,触发跳转。

修复步骤

  1. 完善错误跳转后的处理:在setjmp分支里清理资源并退出程序:
if (setjmp(png_jmpbuf(png_ptr))) {
    printf("error #%d: 读取PNG文件出错\n", 4);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
    return 1;
}
  1. 移除重复读取代码:删掉png_read_image及手动分配行指针的代码,直接用png_get_rows(png_ptr, info_ptr)获取已读取的行数据。
  2. 及时终止错误流程:文件、结构创建失败时,清理已分配资源后立即退出,避免后续无效操作:
FILE *fp = fopen("test.png", "rb");
if (!fp) {
    printf("error #%d: 无法打开文件\n", 1);
    return 1;
}

修复后代码示例

#include <stdio.h>
#include <png.h>

int main(int argc, char* argv[])
{
    printf("starting...\n");
    
    FILE *fp = fopen("test.png", "rb");
    if (!fp) {
        printf("error #%d: 无法打开文件\n", 1);
        return 1;
    }  

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        printf("error #%d: 创建PNG读取结构失败\n", 2);
        fclose(fp);
        return 1;
    }

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        printf("error #%d: 创建PNG信息结构失败\n", 3);
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(fp);
        return 1;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        printf("error #%d: 读取PNG文件出错\n", 4);
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        fclose(fp);
        return 1;
    }    

    png_init_io(png_ptr, fp);

    printf("before png_read_png\n");
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
    printf("png_read_png执行完成,后续代码正常运行\n");

    // 获取图像信息
    png_uint_32 width, height;
    int bit_depth, color_type;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
    printf("图像尺寸:%ux%u,位深:%d,颜色类型:%d\n", width, height, bit_depth, color_type);

    // 获取已读取的行指针
    png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
    // 此处可添加图像数据处理逻辑

    // 清理资源
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(fp);
    
    return 0;
}

额外技巧

可以给libpng设置自定义错误回调,获取更详细的错误信息:

void png_error_fn(png_structp png_ptr, png_const_charp msg) {
    fprintf(stderr, "PNG错误详情: %s\n", msg);
    longjmp(png_jmpbuf(png_ptr), 1);
}

// 创建读取结构时传入回调
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_fn, NULL);

内容的提问来源于stack exchange,提问作者user353885

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:25:17