Search code examples
c++libpng

C++/libpng - fclose() "triggers a breakpoint" after a call to png_write_png()


I remade a function I found in a tutorial for testing purposes, where I just fill a 512 by 512 canvas with pixels of different colors and save that to a file. Then the title happens. Should I comment the call to png_write_png() out, no breakpoints are left in sight.

int save_test_png()
{
    const string path = "D:\\test.png";
    const size_t X = 512, Y = 512;
    const size_t PIXEL_SIZE = 4;
    const size_t BIT_DEPTH = 8;

    FILE* image_file_ptr;
    png_structp png_ptr = nullptr;
    png_infop info_ptr = nullptr;
    png_byte** row_pointers = nullptr;

    int status = 0;

    if (fopen_s(&image_file_ptr, path.c_str(), "wb"))
    {
        return -1;
    }

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        if (image_file_ptr)
        {
            fclose(image_file_ptr);
        }
        return -2;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        if (image_file_ptr)
        {
            fclose(image_file_ptr);
        }
        return -3;
    }

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        if (image_file_ptr)
        {
            fclose(image_file_ptr);
        }
        return -4;
    }

    png_set_IHDR(png_ptr,
        info_ptr,
        X, Y,
        BIT_DEPTH,
        PNG_COLOR_TYPE_RGBA,
        PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT,
        PNG_FILTER_TYPE_DEFAULT);

    row_pointers = static_cast<png_byte**>(png_malloc(png_ptr, Y * sizeof(png_byte*)));
    for (size_t y = 0; y < Y; y++)
    {
        png_byte* row = static_cast<png_byte*>(png_malloc(png_ptr, sizeof(png_byte) * X * PIXEL_SIZE));
        row_pointers[y] = row;
        for (size_t x = 0; x < X; x++)
        {
            *row++ = (x & 0x3F) << 2;                           // red
            *row++ = ((x & 0x1C0) >> 1) | ((y & 0x1C0) >> 4);   // green
            *row++ = (y & 0x3F) << 2;                           // blue
            *row++ = 0xFF;                                      // alpha
        }
    }

    png_init_io(png_ptr, image_file_ptr);
    png_set_rows(png_ptr, info_ptr, row_pointers);
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    status = 0;

    for (size_t y = 0; y < Y; y++)
    {
        png_free(png_ptr, row_pointers[y]);
    }
    png_free(png_ptr, row_pointers);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(image_file_ptr);

    return status;
}

I built libpng and zlib from source, using the Visual Studio solutions that came with the official releases. The project is currently configured as Debug x64, .lib and .dll files for libpng and zlib were built in Release x64 configuration as suggested in the manual. "AppName.exe triggered a breakpoint" also disappears if I reconfigure the project I'm working on as Release x64.


Solution

  • The "triggered a breakpoint" exception disappeared when I linked my Debug x64 configuration to .lib files built under a Debug x64 configuration and also placed a .dll file built under the same configuration in the project's x64/Debug folder, where the executable file is located.