82426


SDL2を使って見たんですが、C言語は詳しくありませんでした。普通の画像描画のプログラムですが問題なく動かしました。でもプログラムを閉じた後祭には妙な文字？エラーが出ました。

閉じた後のエラー

[code]

    $ ./main 
    corrupted size vs. prev_size
    Aborted
    
[/code]

たまには、こういうもありました。

[code]

    $ ./main 
    double free or corruption (out)
    Aborted
    
[/code]

main.c

[code]

    #include "texture.h"
    
    int main() {
        Init();
    
        Texture* img;
        img = loadImage("../../Images/BGR/sky07.jpg");
    
        while (1) {
            if (SDL_PollEvent(&event)) {
                if (event.type == SDL_QUIT) {
                    break;
                }
            }
            Clear();
            Draw(img);
            Display();
        }
    
        Destroy(img);
    
        Close();
    
        return 0;
    }
    
[/code]

texture.h

[code]

    #pragma once
    
    #include <SDL2/SDL.h>
    #include <SDL2/SDL_image.h>
    #include <stdlib.h>
    
    SDL_Window* window;
    SDL_Renderer* renderer;
    SDL_Event event;
    
    typedef struct _Texture Texture;
    
    void Init();
    void Close();
    
    void Clear();
    void Display();
    
    Texture* loadImage(const char* path);
    void Draw(Texture* tex);
    void Destroy(Texture* tex);
    
[/code]

texture.c

[code]

    #include "texture.h"
    
    #define WINDOW_W 800
    #define WINDOW_H 600
    
    typedef struct _Texture {
        int x, y, w, h;
        SDL_Texture* texture;
        SDL_Rect* dst;
        SDL_Rect* src;
    }Texture;
    
    void Init() {
        SDL_Init(SDL_INIT_EVERYTHING);
        IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
        
        window = SDL_CreateWindow(
            "",
            SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
            WINDOW_W, WINDOW_H,
            SDL_WINDOW_SHOWN
        );
    
        renderer = SDL_CreateRenderer(
            window,
            -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
        );
    }
    
    void Close() {
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        IMG_Quit();
        SDL_Quit();
    }
    
    void Clear() {
        SDL_RenderClear(renderer);
    }
    
    void Display() {
        SDL_RenderPresent(renderer);
    }
    
    Texture* loadImage(const char* path) {
        Texture* tex;
    
        tex = malloc(sizeof(Texture*));
        tex->texture = malloc(sizeof(SDL_Texture*));
        tex->dst = malloc(sizeof(SDL_Rect*));
        
        SDL_Surface* surface = IMG_Load(path);
        tex->texture = SDL_CreateTextureFromSurface(renderer, surface);
        tex->dst->x = 0;
        tex->dst->y = 0;
        tex->dst->w = surface->w;
        tex->dst->h = surface->h;
        SDL_FreeSurface(surface);
    
        return tex;
    }
    
    void Draw(Texture* tex) {
        SDL_RenderCopy(renderer, tex->texture, NULL, tex->dst);
    }
    
    void Destroy(Texture* tex) {
        SDL_DestroyTexture(tex->texture);
    }
    
[/code]

Makefile

[code]

    CC := gcc
    LDLIBS := -lSDL2 -lSDL2_image
    
    main: main.c texture.c
    
[/code]

ありがとうございました


CC BY-SA 4.0
2021-09-11T12:20:56.427
82425
2021-09-11T16:55:06.613
2021-09-11T16:55:06.613
2238
47912
question
c sdl
corrupted size vs. prev_size


`tex = malloc(sizeof(Texture*));`や`tex->dst =
malloc(sizeof(SDL_Rect*));`で`Texture`や`SDL_Rect`のサイズではなく、それをを指すポインタのサイズだけメモリを確保して、

[code]

    tex->dst->x = 0;
    tex->dst->y = 0;
    tex->dst->w = surface->w;
    tex->dst->h = surface->h;
    
[/code]

のように`Texture`や`SDL_Rect`の分だけ書き込んでいるのでメモリ破壊が起きてています。  
しかし後続のデータが無いのでバグが顕在化せず、`free()`時点でlibcのチェックに引っかかり警告が出ています。

[code]

    tex = malloc(sizeof(Texture*));
    tex->texture = malloc(sizeof(SDL_Texture*));
    tex->dst = malloc(sizeof(SDL_Rect*));
    
[/code]

を

[code]

    tex = malloc(sizeof(Texture));
    tex->dst = malloc(sizeof(SDL_Rect));
    
[/code]

とすると解決すると思います。

直接関係ありませんが追加でいくつか潜在的な問題があります。

  * `SDL_CreateTextureFromSurface`はテクスチャを表す構造体のメモリを確保し返すので`tex->texture = malloc(sizeof(SDL_Texture*));`は不要です。
  * dstやsrcをポインタとして扱う強い意図が無ければ、ポインタではなく `SDL_Rect dst; SDL_Rect src;` のほうが`tex = malloc(sizeof(Texture));`だけで済んで手軽です。
  * 終了前に解放する使い方だけであれば問題ありませんが、一般には`Destroy(Texture* tex)`に`free(tex);`も必要です。


CC BY-SA 4.0
2021-09-11T13:03:34.520
82426
2021-09-11T13:03:34.520
241
82425
answer