繁体   English   中英

为什么我的这段代码出现分段错误?

[英]Why am I getting a segmentation fault with this code?

尝试在C中制作一个简单的矩形/装箱机。采用给定的面积并找到任何给定尺寸的矩形的位置。

大约4次递归之后是我遇到细分错误时。

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

typedef struct node_type PackNode;
struct node_type {
 int x , y;
 int width , height;
 int used;
 struct node_type *left;
 struct node_type *right;
};

typedef struct point_type PackPoint;
struct point_type {
 int x,y;
};


PackNode _clone(PackNode *node) {
 PackNode clone;
 clone.used = 0;
 clone.x = node->x;
 clone.y = node->y;
 clone.width = node->width;
 clone.height= node->height;
 clone.left = NULL;
 clone.right= NULL;
 return clone;
}
PackNode root;
int rcount;

PackPoint* recursiveFind(PackNode *node, int w, int h) {
 PackPoint rp;
 PackPoint *p = NULL;
 rcount++;
 printf ("rcount = %u\n", rcount);


 //left is not null go to left, if left didn't work try right.
 if (node->left!=NULL) {
  //move down to left branch

  p = recursiveFind(node->left, w, h);
  if (p!=NULL) {
   return p;
  } else {
   p =  recursiveFind(node->right, w, h);
   return p;
  }

 } else {
  //If used just return null and possible go to the right branch;
  if (node->used==1 || w > node->width || h > node->height) {

   return p;
  }

  //if current node is exact size and hasn't been used it return the x,y of the mid-point of the rectangle
  if (w==node->width && h == node->height) {

   node->used=1;


   rp.x = node->x+(w/2);
   rp.y = node->y+(h/2);

   p = &rp;
   return p;
  }


  //If rectangle wasn't exact fit, create branches from cloning it's parent.

  PackNode l_clone = _clone(node);
  PackNode r_clone = _clone(node);
  node->left = &l_clone;
  node->right = &r_clone;

  //adjust branches accordingly, split up the current unused areas
  if ( (node->width - w) > (node->height - h) )
  {
   node->left->width = w;
   node->right->x = node->x + w;
   node->right->width = node->width - w;

  } else {
   node->left->height = h;
   node->right->y = node->y + h;
   node->right->height = node->height - h;
  }

  p = recursiveFind(node->left, w, h);
  return p;
 }
 return p;
}





int main(void) {
 root = malloc(
 root.x=0;
 root.y=0;
 root.used=0;
 root.width=1000;
 root.height=1000;
 root.left=NULL;
 root.right=NULL;


 int i;
 PackPoint *pnt;
 int rw;
 int rh;
 for (i=0;i<10;i++) {
  rw = random()%20+1;
  rh = random()%20+1;
  pnt = recursiveFind(&root, rw, rh);
  printf("pnt.x,y: %d,%d\n",pnt->x,pnt->y);
 }



 return 0;

}
 if (node->left!=NULL) {
  //move down to left branch

  p = recursiveFind(node->left, w, h);
  if (p!=NULL) {
   return p;
  } else {
   p =  recursiveFind(node->right, w, h);

您永远不会检查node-> right是否为NULL,因此下一次递归可能会取消引用NULL。

在这种情况下,您将返回一个指向局部变量的指针:

  //if current node is exact size and hasn't been used it return the x,y of the mid-point of the rectangle
  if (w==node->width && h == node->height) {

   node->used=1;


   rp.x = node->x+(w/2);
   rp.y = node->y+(h/2);

   p = &rp;
   return p;
  }

那是很大的禁忌 函数返回后,局部变量不再有效,因此您要返回的指针指向堆栈内存,该内存现在可能用于其他用途。 当您开始这样做时,您正在破坏堆栈,并且程序将开始表现异常。

要解决此问题,您需要执行以下操作之一:(1)让recursiveFind()按值返回PackNode而不是指向PackNode的指针; (2)使用全局/静态PackNode实例,并返回一个指向该实例的指针(请注意,这将使recursiveFind()非线程安全的); 或(3)返回指向动态分配的PackNode实例的PackNode (例如,使用malloc()分配的实例);或 然后,这要求recursiveFind()调用者在不再需要的某个稍后点,对返回的指针调用free()

同样,此代码也是错误的:

  //If rectangle wasn't exact fit, create branches from cloning it's parent.

  PackNode l_clone = _clone(node);
  PackNode r_clone = _clone(node);
  node->left = &l_clone;
  node->right = &r_clone;

您需要在堆上而不是在堆栈上分配l_cloner_clone ,因为同样,一旦此函数返回,这些node指针将不再有效。 我建议_clone()返回指向PackNode的指针(与malloc()一起分配),而不是按值返回完整的PackNode对象。 但是,如果这样做,则调用代码需要知道在以后不再需要该对象时,在返回的指针上调用free()

[此外,实现中保留了以下划线开头的全局范围的标识符,因此应避免使用此类名称; 您应该将_clone()重命名为clone()clonePackNode() ]。

在不仔细查看代码的情况下,您可以尝试使用诸如Valgrind或GDB之类的工具来识别导致分段错误的行号/表达式。 您可以从那里向后工作。

“给人一条鱼; 你今天已经喂饱了他 教人钓鱼; 你已经喂了他一辈子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM