功能上的分段错误

时间:2011-04-23 15:33:55

标签: c arrays segmentation-fault sdl

我正在学习如何使用SDL库进行图形编程,我在下一段代码中遇到了分段错误:

int situador(SDL_Surface * dib,struct sit_per per)
{

    SDL_Rect pos;
    struct sit_per * est;
    est=&per;


    while(est)
    {
        pos.x = est->ac->x;
        pos.y = est->ac->y;
        pos.w = est->ac->img[est->ac->dir]->w;
        pos.h = est->ac->img[est->ac->dir]->h;
        SDL_BlitSurface(est->ac->img[est->ac->dir], NULL, dib, &pos);
        est=est->si;
    }


    return 0;
}

dib变量来自此函数:

SDL_Surface * draw = SDL_CreateRGBSurface(SDL_SWSURFACE, ANCHO, ALTO, 24,rmask, gmask,bmask, amask);

struct sit_per如下:

struct sit_per
{
    struct personaje * ac;
    struct sit_per * si;
};

struct personaje
{
    char des[50];
    SDL_Surface * img[8];
    int dir;
    int x;
    int y;
};

img数组填充了下一个函数:

struct personaje * creador(char * cad)
{
    int x;
    struct personaje * per;

    per=(struct personaje *)malloc(sizeof(struct personaje));
    strcpy(per->des,cad);

    per->img[0] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/0.bmp");
    per->img[1] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/1.bmp");
    per->img[2] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/2.bmp");
    per->img[3] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/3.bmp");
    per->img[4] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/4.bmp");
    per->img[5] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/5.bmp");
    per->img[6] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/6.bmp");
    per->img[7] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/7.bmp");
    per->img[8] = SDL_LoadBMP("/home/andoni/SDL/img/flecha/8.bmp");

    for(x=0;x<9;x++)
        if(!per->img[x])
            x=10;
    if(x==10)
        return NULL;
    else
        return per;
}

我确信通往图像的路线写得很好,我可以说x和y坐标也很合适。

我会提前感谢任何建议。

2 个答案:

答案 0 :(得分:4)

您的代码将9个图像指针加载到8个元素的数组中。

这不是快乐的秘诀。

答案 1 :(得分:1)

您的代码有几个奇怪的地方。

首先,

int situador(SDL_Surface * dib,struct sit_per per)
{
    SDL_Rect pos;
    struct sit_per * est;
    est=&per;

让它成为

int situador(SDL_Surface * dib,struct sit_per *per)
{
    SDL_Rect pos;
    struct sit_per * est = per; // assignment can be made later

只是样式并避免过多的数据并在堆栈上复制。

使用for循环也可以选择;

  for(est = per; est != NULL; est = est->si)

如果一个函数总是返回一个固定值,你就可以使它不返回...;所以,void situador(...)代替int situador(...)

函数creador加载9个图像,当只需要8个图像时(我想每个方向一个),这是段错误的来源;如前所述,不要硬编码(绝对)文件路径。

要退出for循环,请使用 break 关键字,一般避免修改循环变量(除非你有充分的理由,在这里我看不到一个)。同样,for循环循环9个图像,你的数组中只有8个空间。如果您需要第9张图片,则必须编写SDL_Surface * img[9];。这可能会令人困惑,但是当您声明一个数组时,括号之间的数字是项目数,而在访问时,索引是从0开始的,因此最后一个元素的索引为N-1。

所以整个最终作品可以成为

for(x = 0; x < NUM_OF_ELEMENT; x++)
    if(!per->img[x])
        break;
if (x < NUM_OF_ELEMENT)
{
    int y;
    for(y = 0; y < x; y++)
       SDL_func_to_free_loaded_images(per->img[y]);
    free(per);
    return NULL;
}
else
    return per;

通常最好使用命名常量而不是数字; e.g。

#define  NUM_OF_ELEMENT 8
#define  NUM_OF_DES  50

等等

   struct personaje
   {
      char des[NUM_OF_DES];
      SDL_Surface * img[NUM_OF_ELEMENT];
      int dir;
      int x;
      int y;
   };

等等......(当然,您会选择其他名称,例如NUM_OF_DIRS或NUM_OF_IMAGES或您的语言中任何有意义的首选表单)