代码之家  ›  专栏  ›  技术社区  ›  David Jones

使用FreeType加载字体时出现分段故障

  •  1
  • David Jones  · 技术社区  · 12 年前

    我正在尝试将FreeType库与libpng一起使用,以输出一个字形的PNG图像。我的代码编译得很好,但后来遇到了分段错误。以下是gdb的一些调试输出(我不确定该怎么做):

    (gdb) run
    Starting program: /home/david/Desktop/a.out 
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00007ffff76a58a5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
    (gdb) where
    #0  0x00007ffff76a58a5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
    #1  0x00007ffff7bcb298 in png_write_row (png_ptr=0x611320, row=<optimized out>)
        at /usr/include/x86_64-linux-gnu/bits/string3.h:52
    #2  0x00007ffff7bcb56c in png_write_image (png_ptr=0x611320, image=0x60d218)
        at pngwrite.c:608
    #3  0x0000000000400c35 in main ()
    

    下面是代码:

    #include <stdlib.h>
    #include <stdio.h>
    #include <png.h>
    
    #include <ft2build.h>
    #include FT_FREETYPE_H
    
    main() {
    
        // Declare FreeType variables
        FT_Library library;
        FT_Face face;
        FT_GlyphSlot slot;
        FT_UInt glyph_index = 30;
        char* font_file = "/usr/share/fonts/truetype/freefont/FreeMono.ttf";
    
        // Declare PNG variables
        png_uint_32 width = 100;
        png_uint_32 height = 100;
        int bit_depth = 16;
        int color_type = PNG_COLOR_TYPE_GRAY;
        char* file_name = "/home/david/Desktop/out.png";
        png_structp png_ptr;
        png_infop info_ptr;
    
        // Render font
        int error;
        error = FT_Init_FreeType(&library);
        error = FT_New_Face(library, font_file, 0, &face);
        error = FT_Set_Pixel_Sizes(face, 100, 100);
        error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
        error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
    
        if (error) {
            printf("ERROR CODE: %d", error);
        }
    
        // Create a PNG file
        FILE *fp = fopen(file_name, "wb");
    
        // Create the PNG in memory
        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        info_ptr = png_create_info_struct(png_ptr);
        png_init_io(png_ptr, fp);
    
        // Write the header
        png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
        png_write_info(png_ptr, info_ptr);
    
        // Write image data
        slot = face->glyph;
        png_write_image(png_ptr, &slot->bitmap.buffer);
    
        // End write
        png_write_end(png_ptr, NULL);
    
        fclose(fp);
    }
    

    更新

    我正在尝试一种稍微新的方法(使用png_write_row而不是png_write_image)。

    ... SAME AS BEFORE ABOVE ....
    
    // Write image data
    slot = face->glyph;
    
    int x, y, offset;
    for (y = 0; y < slot->bitmap.rows; y++) {
        for (x = 0; x < slot->bitmap.width; x++) {
            offset = y*(slot->bitmap.width) + x;
            png_write_row(png_ptr, &slot->bitmap.buffer[offset]);
        }
    }
    
    // End write
    png_write_end(png_ptr, NULL);
    
    fclose(fp);
    

    }

    现在我得到了一些更有用的libpng错误,但我仍然不确定如何处理它们:

    libpng warning: zstream not in use (internal error)
    libpng error: stream error
    Aborted (core dumped)
    
    1 回复  |  直到 3 年前
        1
  •  1
  •   Hernan Velasquez    12 年前

    两个建议:

    1. 查看所有编译器警告,以查看指针类型是否正确匹配。

    2. 更好地跟踪可能的错误。例如,写这样的东西:

      int error;
      error = FT_Init_FreeType(&library);
      if (error) {
          printf("ERROR CODE: %d", error);
      }
      error = FT_New_Face(library, font_file, 0, &face);
      if (error) {
          printf("ERROR CODE: %d", error);
      }
      error = FT_Set_Pixel_Sizes(face, 100, 100);
      if (error) {
          printf("ERROR CODE: %d", error);
      }
      error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
      if (error) {
          printf("ERROR CODE: %d", error);
      }
      error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
      
      if (error) {
          printf("ERROR CODE: %d", error);
      }
      

    其中一个调用上的任何错误都可能导致指针错位,从而触发分段错误。

    这是显而易见的:

    FILE *fp = fopen(file_name, "wb");
    if ( fp == null ) {
        printf ("Unable to open file for writing"):
    }
    

    但是,例如,如果您试图在没有权限的情况下将文件写入目录,则fp将指向NULL,并出现进一步的分段错误。