数组和指针:分段错误

时间:2013-10-18 03:07:55

标签: c arrays pointers memory segmentation-fault

我正在玩数组和指针并且遇到了这个分段错误。当我在代码中将“p”指针移动到“ptr”指针之下时,任何人都可以解释为什么我在这段代码中出现了这个分段错误,当我注释掉printf语句之一时它会消失:

 typedef struct str{
   char* ptr;
  }str_t;

copy(str_t t){
   char a[12];
   char *p;   //  <------ no error when move below ptr pointer 
   char *ptr;

   printf("t= %s p = %d ptr = %d\n", t, p, ptr);

   strcpy(a, t.ptr);
   printf("a = %s %u\n", a, &a);

   strcpy(ptr, t.ptr);
   printf("ptr = %s %u\n", ptr, &ptr); //<--- comment it error disappears

   p= t.ptr;
   printf("p = %s %u",p, &p);  //<--- comment it error disappears
 }

int main ()
{
  str_t t;
  char app[] = "hello";
  char ap[] ="world";

  t.ptr = ap;
  copy(t);

  printf("%s\n", app);

  return 0;
}

你可以在这里编译代码来查看结果: http://codepad.org/Q7zS8NaC

感谢您访问此问题。

2 个答案:

答案 0 :(得分:5)

strcpy不会在指针p处分配空间来存储字符串。您需要将其声明为数组或使用malloccalloc来分配空间。

试试这个:

 int len = strlen (t.ptr);         // find length of string

 char * ptr = calloc (len + 1, 1); // allocate space for ptr
 if (!ptr) return;                 // error check calloc
 strcpy (ptr, t.ptr);              // copy the string

 char * p = calloc (len + 1, 1);   // do the same thing for p
 if (!p) return;
 strcpy (p, t.ptr);

这将解决您的细分问题。

但是你还有一些错误,主要是格式问题。

  1. %u打印无符号整数。看起来您正在尝试打印指针,因此请改用%p
  2. printf("t= %s p = %d ptr = %d\n", t, p, ptr);完全错了。
    1. 您需要引用t的成员,即t.ptr
    2. p是指针,不是整数。使用%p代替%d
    3. ptr也是一个指针。使用%p%s
  3. 如果您不确定格式,请阅读printf的{​​{3}}。事实上,阅读任何功能的文档,如果你不确定如何使用它 - 你会省去很多麻烦。

答案 1 :(得分:2)

您的代码有几个未定义的行为:

  • 第一个printf使用%d说明符
  • 打印指针
  • 第二次调用strcpy调用尝试写入未初始化指针所指向的内存
  • printf的第二次和第三次调用将指向数组的指针传递给格式说明符%u

删除其中一个指针会导致代码崩溃,但由于存在未定义的行为,代码无法正常运行,并且可能随时崩溃。

以下是修复它的一种方法:

char a[12];
char *p;
char *ptr;

printf("t= %s p = %x ptr = %x\n", t.ptr, (void*)p, (void*)ptr);

strcpy(a, t.ptr);
printf("a = %s %x\n", a, (void*)(&a[0]));
ptr = malloc(strlen(t.ptr)+1);
// In production, check ptr for NULL
strcpy(ptr, t.ptr);
printf("ptr = %s %x\n", ptr, (void*)&ptr);

p= t.ptr;
printf("p = %s %x", p, (void*)&p);
// Release the memory when you are done
free(ptr);