C char双指针

时间:2015-09-17 14:30:55

标签: c pointers

这可能看起来很傻,但我不明白发生了什么......

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

/*
gcc -o test test.c -std=c99 && time ./test

*/


int main(int argc, char **argv)
{
  char **s;
  s =  malloc(10);
  s[0] = malloc(100);
  s[1] = malloc(100);
  s[2] = malloc(100);
  s[3] = malloc(100);
  s[4] = malloc(100);
  s[5] = malloc(100);
  s[6] = malloc(100);
  s[7] = malloc(100);
  s[8] = malloc(100);
  s[9] = malloc(100);

  strcpy(s[0],"test");
  strcpy(s[1],"test");
  strcpy(s[2],"test");
  strcpy(s[3],"test");
  // strcpy(s[4],"test");

  printf("%s", s[0]);

  return 0;
}

如果我取消注释strcpy(s[4],"test");我会遇到段错误。如果我是malloc 149而不是10,我通过将字符串复制到[20]元素来获得seg错误。 我正在编写新的一年,这是我第一次真正感到沮丧...

有人可以解释一下为什么会这样吗?

修改

好的,我的错误。怎么样:

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

/*
gcc -o test test.c -std=c99 && time ./test

*/


int main(int argc, char **argv)
{
  char **ar = NULL;
  ar = malloc(sizeof(**ar) * 10);

  for (int i = 0; i < 10; i++)
  {
      char ic[2];
      sprintf(ic, "%d", i);
      int l = strlen(ic);
      ar[i] = (char*)malloc(sizeof(*ar[i]) * (l + 1));
      strcpy(ar[i], ic);
      // asprintf(&(ar[i]), "%d", i);
      printf("%s\n", ar[0]);
  }

  return 0;
}

获得如下输出:

0
0
0
0
�@
�@
�@
�@
�@
�@

5 个答案:

答案 0 :(得分:5)

更改为s = malloc(10 * sizeof (char *))。你有10个指针的数组(通常每个4个字节),但只分配了10个字节。

答案 1 :(得分:4)

s =  malloc(10);

10指针的内存不足。

s =  malloc(10*sizeof(char *));

而不是写这么多的陈述 -

s[0] = malloc(100);
s[1] = malloc(100);
s[2] = malloc(100);
s[3] = malloc(100);
s[4] = malloc(100);
s[5] = malloc(100);
s[6] = malloc(100);
s[7] = malloc(100);
s[8] = malloc(100);
s[9] = malloc(100);

使用循环。

int i;
for(i=0;i<10;i++)
  {
     s[i]=malloc(100);
  } 

free他们的方式类似。

编辑 -

之后发布的代码
 ar = malloc(sizeof(**ar) * 10);      

应该是 -

  ar = malloc(sizeof(char *)*10);

不要投射malloc的结果。

答案 2 :(得分:3)

这实际上是分配

s =  malloc(10);

基本上为s

分配大约10个字节的内存

现在合法/严格地允许你只使用10个字节甚至不多1个字节,但是记住没有C的边界检查,所以可以写入传递分配的内存(不会产生编译器错误)

您的计划也发生了类似的事情。

程序的内存摘要如下所示(取自valgrind)

==4378== Invalid write of size 8
==4378==    at 0x4005C1: main (t.c:16)
==4378==  Address 0x51fc048 is 8 bytes inside a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x4005D6: main (t.c:17)
==4378==  Address 0x51fc050 is 6 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x4005EB: main (t.c:18)
==4378==  Address 0x51fc058 is 14 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x400600: main (t.c:19)
==4378==  Address 0x51fc060 is 22 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x400615: main (t.c:20)
==4378==  Address 0x51fc068 is not stack'd, malloc'd or (recently) free'd
==4378==
==4378== Invalid write of size 8
==4378==    at 0x40062A: main (t.c:21)
==4378==  Address 0x51fc070 is not stack'd, malloc'd or (recently) free'd
==4378==
==4378== Invalid write of size 8
==4378==    at 0x40063F: main (t.c:22)
==4378==  Address 0x51fc078 is 24 bytes before a block of size 100 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x4005A4: main (t.c:15)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x400654: main (t.c:23)
==4378==  Address 0x51fc080 is 16 bytes before a block of size 100 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x4005A4: main (t.c:15)
==4378==
==4378== Invalid write of size 8
==4378==    at 0x400669: main (t.c:24)
==4378==  Address 0x51fc088 is 8 bytes before a block of size 100 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x4005A4: main (t.c:15)
==4378==
==4378== Invalid read of size 8
==4378==    at 0x400685: main (t.c:27)
==4378==  Address 0x51fc048 is 8 bytes inside a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid read of size 8
==4378==    at 0x40069A: main (t.c:28)
==4378==  Address 0x51fc050 is 6 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid read of size 8
==4378==    at 0x4006AF: main (t.c:29)
==4378==  Address 0x51fc058 is 14 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==
==4378== Invalid read of size 8
==4378==    at 0x4006C4: main (t.c:30)
==4378==  Address 0x51fc060 is 22 bytes after a block of size 10 alloc'd
==4378==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4378==    by 0x400596: main (t.c:14)
==4378==

正如您所看到的那样,使用malloc(10)的prrgram中存在无效的读取和写入;

然而用

替换相同的malloc语句
s = malloc( 10 * sizeof( char * ) );

将立即清除所有错误,除了一件事,清除代码中遗漏的已分配内存。

答案 3 :(得分:2)

s =  malloc(10);

这一行分配10个字节,而不是10个指针!指针存储在几个字节上,通常是今天架构上的4或8个字节。

请改为:

s =  malloc(10*sizeof(char*));

答案 4 :(得分:-3)

s = malloc(10);保留10个字节的内存,但是你需要10个指针的足够内存。你应该使用

//s = malloc(10*sizeof(int)); Wrong
s = malloc(10*sizeof(char*));

编辑:对不起,你是对的应该是char *而不是int,我的错误