【问题标题】:Can't solve Segmentation fault (core dumped) in SDL无法解决 SDL 中的分段错误(核心转储)
【发布时间】:2016-04-21 10:16:29
【问题描述】:

在使用 gdb 或将许多 printfs 放入以下代码之后,我都无法找到分段错误错误发生的位置:

  #include <stdio.h>
  #include <stdlib.h>
  #include <math.h>
  #include "../GCGraLib2/GCGraLib2.h"

  #define DIM 100

这里我们计算一个点和数组中的一组点之间的距离

  float *dist2(int px,int py,int x[],int y[])
  {
  float min,d;int i=1;min=pow(abs(px-x[0]),2)+pow(abs(py-y[0]),2);;
  int nearestp;static float output[2];
    while (i<=DIM) {
          d=pow(abs(px-x[i]),2)+pow(abs(py-y[i]),2);
    if (d<min){min=d;}
        i++;
  }
    nearestp=i-1;
    output[0]=d;output[1]=nearestp;
  return output;
}

这里是下面描述的多边形的重绘

  void redraw(int n, int x[], int y[],SDL_Renderer *ren)
  {
  int i;
  GC_FillCircle(ren,x[0],y[0],3);
    for (i=1; i<=n; i++)
    {
      SDL_RenderDrawLine(ren, x[i-1], y[i-1], x[i], y[i]);
    GC_FillCircle(ren,x[i],y[i],3);
    }
  }

对事件队列使用过滤器

  int isMouseEvent(int * motioncounter,SDL_Event * event) {
    *motioncounter=*motioncounter+1;
  if (*motioncounter<=5) {
          return 0;}
      else {
          *motioncounter=0;
          return 1;
      }
  }

这是用贝塞尔曲线对一组点进行插值

  void bezier(SDL_Renderer *ren, int x[], int y[], int n)
  {
    int i,k,tempo,indice;
    float t = 0;
      float xx[DIM],yy[DIM];
      float bx[DIM],by[DIM];
      printf("BEZIER\n");
      // coefficienti da usare nell'algoritmo
      for (tempo=0;tempo<=99;tempo++)
      {
          for (indice=0;indice<=n;indice++)
          {
              xx[indice]=x[indice];
          }
          for (indice=0;indice<=n;indice++)
          {
              yy[indice]=y[indice];
          }
          for (k=1;k<n;k++)
          {
              for (i=0;i<n-k;i++)
              {
                  // trovo coordinante della curva al tempo t
                  xx[i]=(1-t)*xx[i]+t*xx[i+1];
                  yy[i]=(1-t)*yy[i]+t*yy[i+1];
              }             
          }
          //coordinate del punto
          bx[tempo]=xx[0];
          by[tempo]=yy[0];
          t=t+0.01;
      }
      // aggiornare ren con coordinate curva
      // rendo tutto le schermo nero
      SDL_SetRenderDrawColor(ren, 0, 0, 0, 255);
  SDL_RenderClear(ren);
      // ristampare i punti
      for (i=0;i<n;i++)
      {
          SDL_SetRenderDrawColor(ren, 255, 255, 0, 255);
          GC_FillCircle(ren,x[i],y[i],3);
      }

      for (tempo=0;tempo<=98;tempo++)
      {
          SDL_RenderDrawLine(ren, bx[tempo], by[tempo], bx[tempo+1], by[tempo+1]);
      }

  }

这里我们控制I/O的通量

  int main(void) 
  {
  SDL_Window *win;
  SDL_Renderer *ren;
  SDL_Event event;
  int vxmax,vymax;
  int esc=1,i,j,n=0;SDL_EventFilter prune=0;
  int x[DIM],y[DIM];int readytomove=0;
  float *DIST;float dist;int nearestp;
  Uint32 windowID;int motioncounter=0;

    if(SDL_Init(SDL_INIT_VIDEO)<0)
    {
      fprintf(stderr,"Couldn't init video: %s\n",SDL_GetError());
      return(1);
    }

    vxmax=300;
    vymax=300;

  win= SDL_CreateWindow("Inter_Polygon", 100, 100, vxmax, vymax, 
                           SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  if(win==NULL){
      fprintf(stderr,"SDL_CreateWindow Error: %s\n",SDL_GetError());
      SDL_Quit();
      return 1;
  }

  ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  if (ren == NULL){
      SDL_DestroyWindow(win);
      fprintf(stderr,"SDL_CreateRenderer Error: %s\n",SDL_GetError());
      SDL_Quit();
    return 1;
  }

  SDL_SetRenderDrawColor(ren, 0, 0, 0, 255);
  SDL_RenderClear(ren);
  SDL_SetRenderDrawColor(ren, 255, 0, 50, 255);
   SDL_RenderPresent(ren);

这里我们通过点击一些点来绘制一个多边形。要退出,请按 Esc 键。

  while(esc)
  {
      if (SDL_PollEvent(&event))
          prune=(SDL_EventFilter) isMouseEvent(& motioncounter,&event);
          SDL_SetEventFilter(prune,& motioncounter);
      switch(event.type)
      {
      case SDL_MOUSEBUTTONDOWN:
          if(event.button.button==1)
          {
                  DIST = dist2(event.button.x,event.button.y,x,y);nearestp=DIST[1];dist=DIST[0];
                  if (dist >= 6.5) {
                          readytomove=0;
              x[n]=event.button.x;
              y[n]=event.button.y;
              GC_FillCircle(ren,x[n],y[n],3);
              if(n>1) {
                            printf("CALL TO BEZIER: n=%i\n",n); 
  //            SDL_RenderDrawLine(ren, x[n-1], y[n-1], x[n], y[n]);
                            bezier(ren,x,y,n);
                    n++;
                }
                    else{readytomove=1;}
                    }
                }
             break;
         case SDL_MOUSEMOTION:
          if(event.button.button==1)
          {
                DIST = dist2(event.button.x,event.button.y,x,y);nearestp=DIST[1];dist=DIST[0];
                if (readytomove)
              {
                    x[nearestp]=event.button.x;
                    y[nearestp]=event.button.y;
                    GC_FillCircle(ren,x[1],y[1],3);
                  if(n>0){
                      bezier(ren,x,y,n);
                            n++;
                      }
                  }
              }
           SDL_RenderPresent(ren);
         break;
         case SDL_KEYDOWN:
         if(event.key.keysym.sym == SDLK_ESCAPE)
           esc=0;
         break;
         case SDL_WINDOWEVENT:
             windowID = SDL_GetWindowID(win);
             if (event.window.windowID == windowID)  {
                switch (event.window.event)  {
             case SDL_WINDOWEVENT_SIZE_CHANGED:  {
               vxmax = event.window.data1;
               vymax = event.window.data2;
  //                     printf("vxmax= %d \n vymax= %d \n", vxmax,vymax);
               SDL_SetRenderDrawColor(ren, 0, 0, 0, 255);     
                         SDL_RenderClear(ren);
               SDL_SetRenderDrawColor(ren, 255, 0, 50, 255);
                       redraw(n-1,x,y,ren);
                       SDL_RenderPresent(ren);
                     break;
                   }
               }
            }
         break;

            }
    }

    SDL_Quit();
    return(0);
  }

编译使用

gcc -DDEBUG -c -Wall binter_polygon2ren.c | gcc binter_polygon2ren.o ../GCGraLib2/GCGraLib2.o -L/usr/X11R6/lib -lX11 -lSDL2 -lSDL2_ttf -lSDL2_image -lm -o binter_polygon2re

谢谢。

【问题讨论】:

  • 至少知道 GDB 实际上能够告诉你什么是有帮助的 如果堆栈跟踪看起来很奇怪,那么很有可能你损坏了堆栈。
  • 也许将程序分成几部分。从尝试做一些简单的事情开始,然后添加部分以达到您在此处尝试做的事情。
  • 段错误发生在哪一行?
  • 猜测,当你计算距离时,它应该是 while (i

标签: c segmentation-fault sdl


【解决方案1】:

我注意到我们无法检查完整的控制流,即我看不到您的每个函数在哪里被调用。但我很确定您的数组索引存在错误。

C 中所有大小为 N 的数组都有成员 0..N-1。我看到您在 main 中分配大小为 DIM 的数组,但后来(例如在 dist2 中)我看到数组从 1 索引到 DIM,这导致超出范围的情况,您会覆盖堆栈上的某些内容.

redraw 我看到了:

for (i=1; i<=n; i++)
{
   SDL_RenderDrawLine(ren, x[i-1], y[i-1], x[i], y[i]);

我注意到它会超出范围。这应该是:

for (i=1; i<n; i++)
{
    SDL_RenderDrawLine(ren, x[i-1], y[i-1], x[i], y[i]);

我建议您彻底检查所有索引和数组边界。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多