程序以状态3 SDL结尾

时间:2018-06-14 16:13:45

标签: c sdl

以下程序每次启动时都会以状态3结束。

#include "amr-0-1.h"
#include "SDL_sys.c"

int screen_w=351, screen_h=234;
int ss_w=screen_w*(5/9), ss_h=screen_h*(11/19);
int m_w=screen_w*(7/27), m_h=screen_h*(175/234);
int g_w=screen_w*(100/351), g_h=screen_h*(2/9);
int mo_w=screen_w*(29/117), mo_h=screen_h*(1/13);
int ss_mo_w=screen_w*(17/117), ss_mo_h=screen_h*(4/117);
int p_d=32, border=2;

SDL_Surface *screen = NULL; //Fenetre principale
SDL_Surface *m = NULL;      //Surface du menu
SDL_Surface *mo = NULL;     //Surface d'une option menu
SDL_Surface *ss = NULL;     //Surface de la zone d'écran secondaire
SDL_Surface *ss_mo = NULL;  //Surface d'une option du sous-menu
SDL_Surface *p = NULL;      //Surface destinée à accueillir l'image utilisateur

SDL_Rect c_m;
SDL_Rect c_mo;
SDL_Rect c_ss;
SDL_Rect c_ss_mo;
SDL_Rect c_p;
SDL_Rect c_screen;

int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
fprintf(stderr, "Erreur d'initialisation de la SDL");
exit(EXIT_FAILURE);
}
SGI_Init(1, screen, 351, 234, NULL, 0, 0, &c_screen); //Écran principal
SGI_Init(0, m, m_w, m_h, screen, 39, 58, &c_m); //Menu
SGI_Init(0, ss, ss_w, ss_h, screen, 156, 78, &c_ss); //Surface d'écran secondaire
pause();
SDL_Quit();
return EXIT_SUCCESS;
}

根据我的研究,状态3代表SegFault'所以它是一个(或多个)SDL'的分配问题。表面。以下是我分配表面的方法:

#include "amr-0-1.h"

void pause()
{
int continuer = 1;
SDL_Event event;

while (continuer)
{
SDL_WaitEvent(&event);
switch(event.type)
{
case SDL_QUIT:
continuer = 0;
}
}
}

int SGI_Init(int command, SDL_Surface *child, int child_w, int child_h, SDL_Surface *mother, int x, int y, SDL_Rect* cursor)
{
if(command)
{
child = SDL_SetVideoMode(child_w, child_h, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
return 1;
}
else if(!command)
{
child = SDL_CreateRGBSurface(SDL_HWSURFACE, child_w, child_h, 32, 0,0,0,0);
SDL_FillRect(child, cursor, SDL_MapRGB(mother->format,255,255,255));
cursor->x=x;
cursor->y=y;
SDL_BlitSurface(child, NULL, mother, cursor);
SDL_Flip(mother);
return 1;
}
else
{
return 0;
}
}

标题amr-0-1.h:

#include <stdlib.h>
#include <stdio.h>
#include <SDL.h>

void pause();
int SGI_Init(int command, SDL_Surface *child, int child_w, int child_h, SDL_Surface *mother, int x, int y, SDL_Rect* cursor);

我无法找到分配错误的原因 我使用SDL 1.2和CodeBlocks 17.12,我也是一个菜鸟,我是法国人,所以请耐心等待我慢!

1 个答案:

答案 0 :(得分:1)

即时SEGFAULT可能是由

引起的
SDL_FillRect(child, cursor, SDL_MapRGB(mother->format,255,255,255));

背后的原因在keltar的评论中得到了回答:

在这一行:

SGI_Init(1, screen, 351, 234, NULL, 0, 0, &c_screen); 

您传入screen以初始化它。 这里发生的是screen被复制到 local 变量child中。 然后修改child,但这发生在screen副本screen本身保持不变。 您可能会对screen是指针这一事实感到困惑。 但是,您想要修改指针,因此您需要一个指向指针的指针,如下所示:

int SGI_Init(int command, SDL_Surface **child, int child_w, int child_h, SDL_Surface *mother, int x, int y, SDL_Rect* cursor)
    {

        if(command)
        {
            *child = SDL_SetVideoMode(child_w, child_h, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
            return 1;
        }
        else if(!command)
        {
            *child = SDL_CreateRGBSurface(SDL_HWSURFACE, child_w, child_h, 32, 0,0,0,0);
            SDL_FillRect(*child, cursor, SDL_MapRGB(mother->format,255,255,255));
            cursor->x=x;
            cursor->y=y;
            SDL_BlitSurface(*child, NULL, mother, cursor);
            SDL_Flip(mother);
            return 1;
        }
        else
        {
            return 0;
        }
    }


    int main(int argc, char *argv[])
    {
        if (SDL_Init(SDL_INIT_VIDEO) == -1)
        {
            fprintf(stderr, "Erreur d'initialisation de la SDL");
            exit(EXIT_FAILURE);
        }

        SGI_Init(1, &screen, 351, 234, NULL, 0, 0, &c_screen); //Écran principal
        printf("%p\n", screen);
    SGI_Init(0, &m, m_w, m_h, screen, 39, 58, &c_m); //Menu
    SGI_Init(0, &ss, ss_w, ss_h, screen, 156, 78, &c_ss); //Surface d'écran secondaire
        pause();
        SDL_Quit();
        return EXIT_SUCCESS;
    }

但为什么不直接返回新的SDL_Surface

SDL_Surface* SGI_Init(int command, int child_w, int child_h, SDL_Surface *mother, int x, int y, SDL_Rect* cursor)
{

    if(command)
    {
        return SDL_SetVideoMode(child_w, child_h, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
    }
    else if(!command)
    {
        SDL_Surface* child = SDL_CreateRGBSurface(SDL_HWSURFACE, child_w, child_h, 32, 0,0,0,0);
        SDL_FillRect(child, cursor, SDL_MapRGB(mother->format,255,255,255));
        cursor->x=x;
        cursor->y=y;
        SDL_BlitSurface(child, NULL, mother, cursor);
        SDL_Flip(mother);
        return child;
    }
    else
    {
        return 0;
    }
}


int main(int argc, char *argv[])
{
    if (SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        fprintf(stderr, "Erreur d'initialisation de la SDL");
        exit(EXIT_FAILURE);
    }

    screen = SGI_Init(1, 351, 234, NULL, 0, 0, &c_screen); //Écran principal
    printf("%p\n", screen);
    m = SGI_Init(0, m_w, m_h, screen, 39, 58, &c_m); //Menu
    ss = SGI_Init(0, ss_w, ss_h, screen, 156, 78, &c_ss); //Surface d'écran secondaire
    pause();
    SDL_Quit();
    return EXIT_SUCCESS;
}

您的代码中有一些可能导致未定义行为的内容,例如

SDL_Rect c_m;
SDL_Rect c_mo;
SDL_Rect c_ss;
...

声明变量,但是你永远不会初始化它们,你只需将它们作为参数传递给函数。如果在初始化之前曾经读过其中一个,则会造成未定义的行为。

即便如此,那里有很多代码味道,command参数显而易见的是最引人注目的一个:你的SDI_Init函数做了两件完全不同的事情。您应该尝试坚持single responsibility principle并将功能分成两个功能 - 每个任务一个。如果您想坚持自己的设计,至少可以使用适当的enum command ...