可以在C代码中查找Segfault

时间:2015-03-29 21:10:41

标签: c

每次运行我的程序时,都会遇到此错误,但我似乎无法弄清楚导致它的原因。该程序假设从文本文件&中获取输入。然后创建一个光线跟踪器的输出ppm文件。谢谢!

/** genRay **/
vector_t genRay(scene_t *scene, int column, int row) 
{
   vector_t direction;
   entity_t    *ent;
   window_t *window;

   assert(scene->magic == SCENE_T);
   ent = scene->window;
   window = ent->entDerived;
   assert(window->magic == WINDOW_T);

   /* Computer the pixel's real scene coordinates */
   direction.x = ((double)(column)/
      (double)(scene->picture->columns-1))*window->windowWidth;
   direction.x -= window->windowWidth/2.0;
   direction.y = ((double)(row)/
      (double)(scene->picture->rows-1))*window->windowHeight;
   direction.y -= window->windowHeight/2.0;
   direction.z = 0;

   /* And now construct a unit vector from the view point to the pixel */
   direction = ray(window->viewPoint, direction);
   direction = unitize(direction);
   return(direction);
} /* End genRay */



/**
 * The raytrace() function traces a single ray and returns 
 * the composite 
 * intensity of the light it encounters. It is recursive and 
 * so the start of the ray cannot be assumed to be the viewpt 
 * Recursion won't be involved until we take on specular light 
**/
intensity_t rayTrace(scene_t *scene, point_t base, vector_t unitDir,
                 double total_dist, entity_t *self) {
	intensity_t intensity = ((intensity_t){0, 0, 0});
	entity_t * closestEnt;
	hitinfo_t * hit = malloc(sizeof(hitinfo_t));
	closestEnt = closest(scene, base, unitDir, self, hit);

	if (closestEnt == NULL) {
		free(hit);
		return (intensity);
	}

	total_dist += hit->distance;

	window_t * window = ((window_t *)(scene->window->entDerived));
	sobj_t * sobj = ((sobj_t *)(closestEnt->entDerived));

	intensity = ((tuple_t){window->ambient.x * sobj->color.r,
		window->ambient.y * sobj->color.g,
		window->ambient.z * sobj->color.b});

	sobj_t * closestSobj = closestEnt->entDerived;
	if (length(((tuple_t)(closestSobj->reflective))) != 0) {
		vector_t U = scale(unitDir, -1);
		vector_t N = hit->normal;
		vector_t V = unitize(add(scale(N, (2 * dot(U, N))), unitDir));
		intensity_t reflection;

		reflection = rayTrace(scene, hit->hitpoint, V, total_dist, closestEnt);		
		intensity = add(intensity, reflection);
	}

	free(hit);
return (intensity);

} /* End rayTrace */

/**
 * The closest() function processes each scene object in the scene 
 * objects list (sobjList) and uses the "hits" functions to determine 
 * if the ray hits the scene object. If the ray hits one or more
 * scene objects,  the function determines the closest object hit 
 * and updates the fields of the hitinfo_t pointed.  The function 
 * returns the pointer to the closest entity, or NULL if the ray 
 * doesn't hit anything.
**/

entity_t *closest(scene_t *scene, point_t base, vector_t unitDir, 
                  entity_t *self, hitinfo_t *hit) {

int flag_closest = 0;
entity_t * ent; //Shortcut to entity in list
sobj_t * sobj; //Shortcut to ent->entDerived
entity_t * closest = NULL; //Will be returned at end of function
hitinfo_t hit_closest;
iterator_t * iter = newIterator(scene->sobjList);

l_begin(iter);
while((ent = l_next(iter)) != NULL) {
	/** Run Hit Checks and stores closest Entity **/
	if (ent != self) {
		sobj = ent->entDerived;
		if (sobj->hits(ent, base, unitDir, &hit_closest) == 1) {
			if (flag_closest == 1) {
				if (hit->distance > hit_closest.distance) {
					hit->distance = hit_closest.distance;
					hit->normal = hit_closest.normal;
					hit->hitpoint = hit_closest.hitpoint;
					closest = ent;
				}
			}

			else { //first time there has been a "hit"
				hit->distance = hit_closest.distance;
				hit->normal = hit_closest.normal;
				hit->hitpoint = hit_closest.hitpoint;
				flag_closest = 1;
				closest = ent;
			}
		} 
	}
}
free(iter);
return closest;
} /* End closest */

#include "ray.h"

/** newPlane **/
entity_t *newPlane(char *enttype, int code) 
{
   entity_t *ent;
   plane_t *plane;
   vector_t zero = {0, 0, 0};
   
   ent = newSceneObj(enttype, code);
   plane = malloc(sizeof(plane_t));
   assert(plane != NULL);
   ((sobj_t *)(ent->entDerived))->sobjDerived = plane; // create new plane

   plane->point = zero;
   plane->orient1 = (vector_t){1, 0, 0}; // setting default values for plane
   plane->orient2 = (vector_t){0, 1, 0};

   plane->magic = PLANE_T; 

   return(ent);
}

/** loadPlane **/
void loadPlane(FILE *inFP, entity_t *ent) 
{
   char *attributes[] = {"point", "orient1", "orient2", NULL};
   char attribute[25];
   int ndx;
   assert(ent->magic == ENTITY_T);
   sobj_t *obj = ent->entDerived;
   assert(obj->magic == SCENEOBJ_T);
   plane_t *plane = obj->sobjDerived;
   assert(plane->magic == PLANE_T);

   loadSceneObj(inFP, ent);
   
   fscanf(inFP, "%s", attribute);

   while(attribute[0] != ';')
   {
      ndx = getindex(attribute, attributes);

      switch (ndx) {
      case 0:
         /* point */
         plane->point = readTuple(inFP, "Could not read plane point");
         break;

      case 1:
         /* orient1 */
         plane->orient1 = readTuple(inFP, "Could not read plane orient1");
         break;

      case 2:
         /* orient1 */
         plane->orient2 = readTuple(inFP, "Could not read plane orient2");
         break;

      default:
         fprintf(stderr, "bad plane attribute; exiting\n");
         exit(1); 
      }
      fscanf(inFP, "%s", attribute);
   }
}

/** completePlane **/
void completePlane(scene_t *scene, entity_t *ent) 
{
    sobj_t *sobj;
    plane_t *plane;
    assert(scene->magic == SCENE_T);
    assert(ent->magic == ENTITY_T);
    sobj = ent->entDerived;
    assert(sobj->magic == SCENEOBJ_T);
    plane = sobj->sobjDerived;
    assert(plane->magic == PLANE_T);
    plane->normal = unitize(cross(plane->orient1, plane->orient2));
    completeSceneObj(scene, ent);
}

/** dumpPlane **/
void dumpPlane(FILE *outFP, entity_t *ent) 
{
    assert(ent->magic == ENTITY_T);
    sobj_t *sobj = ent->entDerived;
    assert(sobj->magic == SCENEOBJ_T);
    plane_t *plane = sobj->sobjDerived;
    assert(plane->magic == PLANE_T);
    dumpSceneObj(outFP, ent);
    printTuple(outFP, "  point:     ", plane->point);
    printTuple(outFP, "  normal:    ", plane->normal);
}


int hitPlane(entity_t *ent, point_t base, vector_t dir, hitinfo_t *hit) {
    assert(ent->magic == ENTITY_T);
    sobj_t *sobj =  ent->entDerived;     
    assert(sobj->magic == SCENEOBJ_T);
    plane_t *planePtr = sobj->sobjDerived;
    assert(planePtr->magic == PLANE_T);

    point_t  Q = planePtr->point;      // Point data
    vector_t N = planePtr->normal;	// Normal data     
    vector_t D = dir;          // Direction vector
    point_t  V = base;		// Base coordinates
    point_t  H;           // Hit point                 
    double t;		// Distance

    if (dot(N, D) == 0)
        return 0; // parallel
    
    t = (dot(N, Q) - dot(N, V))/
           dot(N, D);

    if (t < 0)
        return 0; // behind me
    
    H = scale(D, t); 
    H = add(H, V);
    if (H.z > 0) {
        return 0; // between me & the screen
    } 
    
    hit->hitpoint = H;
    hit->normal = unitize(N);
    hit->distance = t;
    if (dot(D, hit->normal) > 0) { // adjust normal depending on which side the ray hit
        hit->normal = scale(hit->normal, -1);
    }

    return 0;
}

#include "ray.h"

/** newSphere **/
entity_t *newSphere(char *enttype, int code) 
{
   entity_t *ent;
   sphere_t *sphere;
   vector_t zero = {0, 0, 0};

   ent = newSceneObj(enttype, code);
   sphere = malloc(sizeof(sphere_t));
   assert(sphere != NULL);
   ((sobj_t *)(ent->entDerived))->sobjDerived = sphere; // create sphere
   sphere->center = zero;
   sphere->radius = 1;
   sphere->magic = SPHERE_T; // set default values

   return(ent);
}

/** loadSphere **/
void loadSphere(FILE *inFP, entity_t *ent) 
{

   char *attributes[] = {"center", "radius", NULL};
   char attribute[25];

   int ndx;
   assert(ent->magic == ENTITY_T);
   sobj_t *obj = ent->entDerived;
   assert(obj->magic == SCENEOBJ_T);
   sphere_t *sphere = obj->sobjDerived;
   assert(sphere->magic == SPHERE_T);

   loadSceneObj(inFP, ent);
   
   fscanf(inFP, "%s", attribute);
   while(attribute[0] != ';')
   {
       ndx = getindex(attribute, attributes);

       switch (ndx) 
       {
         case 0:
           /** center **/
           sphere->center = readTuple(inFP, 
              "Could not read sphere center coordinates");
         break;

         case 1:
           /** radius **/
           sphere->radius = readDouble(inFP, "Could not read sphere radius");
         break;

         default:
           fprintf(stderr, "bad sphere attribute; exiting\n");
           exit(1);
      }
      fscanf(inFP, "%s", attribute);
   }
}


/** completeShere **/
void completeSphere(scene_t *scene, entity_t *ent) {
     assert(scene->magic == SCENE_T);
     assert(ent->magic == ENTITY_T);
     completeSceneObj(scene, ent);
}

/** dumpSphere **/
void dumpSphere(FILE *out, entity_t *ent) {
   assert(ent->magic == ENTITY_T);
   sobj_t *obj = ent->entDerived;
   assert(obj->magic == SCENEOBJ_T);
   sphere_t *sphere = obj->sobjDerived;
   assert(sphere->magic == SPHERE_T);

   dumpSceneObj(out, ent);
   printTuple(out,  "   center:    ", sphere->center);
   fprintf(out,     "   radius:     %8.4lf\n",
            sphere->radius);
}

/** hitSphere **/
int hitSphere(entity_t *ent, point_t base, vector_t dir, hitinfo_t *hit) 
{
/** asserts **/
assert(ent->magic == ENTITY_T);
sobj_t * sobj = ent->entDerived;
assert(sobj->magic == SCENEOBJ_T);
sphere_t * sphere = sobj->sobjDerived;
assert(sphere->magic == SPHERE_T);
point_t V = base; //View/Starting point
vector_t D = dir; //Unit vector in direction of travel
point_t C = sphere->center; //Center of the sphere
double r = sphere->radius; //Radius of the sphere
point_t Cp = add(C, scale(C, (-1))); //Adjusted center of sphere (0,0,0)
point_t Vp = add(V, scale(C, (-1))); //Adjust viewpoint of sphere
double t;
if (length(Cp) != 0) fprintf(stderr, "Cp does not equal (0,0,0)\n");
//Quadratic formula to determine distance and if a hit occured
double a = dot(D, D);
double b = (dot(Vp, D) * 2.0);
double c = (dot(Vp, Vp) - pow(r, 2));
t = (pow(b, 2) - (4 * a * c)); //dscriminant
if (t <= 0) return 0; //miss
t = ((b*(-1) - pow(t, 1.0/2))/(2 * a)); //quadratic equation
if (t < 0) return 0; //behind us
hit->hitpoint = add(V, scale(D, t));
if (hit->hitpoint.z > 0) return 0;
hit->normal = add(hit->hitpoint, scale(C, (-1)));
hit->normal = unitize(hit->normal);
hit->distance = t;
return 1;
}

#include "ray.h"

/** render **/
/* The render() function invokes makePixel() to set the color of each 
 * pixel in the window
 *
 * input parameter: 
 *   a pointer to the scene
 * return value:
 *   none
 *
 * method/effect:
 *   the color of each pixel is set for each pixel in the window 
 *
 * typical calling sequence:
 *   render(scene)
 *
 * local variables:
 *   picture - a pointer to the image
 *   currPix - a pointer to the current pixel beign painted.
 *   row - a lcv for processing each row (the height) of the image
 *   col - a lcv for processing each column (the width) of the image
 */
void render(scene_t *scene) 
{
    /* Get pointer to picture data */
    assert(scene->magic == SCENE_T);
    image_t *picture = scene->picture;
    
    /* Work directly with an increasing pointer */
    pixel_t *currPix = picture->image;
    int row, col;
    for(row = picture->rows - 1; row >= 0; row--)   /* Bottom row of  */
       for(col = 0; col < picture->columns; col++)  /* image is row 0 */
           *currPix++ = makePixel(scene, col, row); /* Left column    */
                                                    /* of image is    */
                                                    /* column 0       */

} /* End render */

/** makePixel **/
pixel_t makePixel(scene_t *scene, int colndx, int rowndx) 
{
intensity_t intensity;
vector_t dir;
window_t * windowPtr;
dir = genRay(scene, colndx, rowndx);
windowPtr = scene->window->entDerived;
intensity = rayTrace(scene, windowPtr->viewPoint, dir, 0.0, NULL);
if (intensity.x > 1.0) intensity.x = 1.0;
if (intensity.y > 1.0) intensity.y = 1.0;
if (intensity.z > 1.0) intensity.z = 1.0;
return((pixel_t){(255 * intensity.x),
(255 * intensity.y),
(255 * intensity.z)});
} /* End makePixel */

1 个答案:

答案 0 :(得分:2)

Valgrind和GDB非常有用。

我之前使用的最前一个是GDB-我喜欢它,因为它向我显示了Segmentation Fault所在的确切行号。

以下是一些可以指导您使用GDB的资源:

GDB Tutorial 1

GDB Tutorial 2

如果你仍然无法弄清楚如何在这些教程中使用GDB,那么谷歌就有很多!只需使用GDB搜索调试分段错误!

祝你好运:)