簡體   English   中英

C char 雙指針

[英]C char double pointer

這可能看起來很傻,但我不明白發生了什么......

#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] 元素來獲得段錯誤。 我正在用 c 編碼一年,這是我第一次真正感到傾倒......

有人可以解釋我為什么會這樣嗎?

編輯

好吧,我的錯。 關於什么:

#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
�@
�@
�@
�@
�@
�@

更改為s = malloc(10 * sizeof (char *)) 您有 10 個指針(通常每個 4 個字節)的數組,但只分配了 10 個字節。

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結果。

那么這實際上分配

s =  malloc(10);

基本上為 s 分配了大約 10 字節的內存

現在合法/嚴格你只允許使用 10 個字節,甚至不能使用 1 個字節,但請記住,C 沒有邊界檢查,因此可以寫通過分配的內存(不會產生編譯器錯誤)

你的程序也發生了類似的事情。

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

 ==4378== Invalid write of size 8 ==4378== at 0x4005C1: main (tc: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 (tc:14) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x4005D6: main (tc: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 (tc:14) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x4005EB: main (tc: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 (tc:14) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x400600: main (tc: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 (tc:14) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x400615: main (tc: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 (tc: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 (tc: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 (tc:15) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x400654: main (tc: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 (tc:15) ==4378== ==4378== Invalid write of size 8 ==4378== at 0x400669: main (tc: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 (tc:15) ==4378== ==4378== Invalid read of size 8 ==4378== at 0x400685: main (tc: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 (tc:14) ==4378== ==4378== Invalid read of size 8 ==4378== at 0x40069A: main (tc: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 (tc:14) ==4378== ==4378== Invalid read of size 8 ==4378== at 0x4006AF: main (tc: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 (tc:14) ==4378== ==4378== Invalid read of size 8 ==4378== at 0x4006C4: main (tc: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 (tc:14) ==4378==

如您所見,使用 malloc(10) 對整個 prrgram 進行了無效的讀取和寫入;

但是用相同的 malloc 語句替換

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

將立即清除除一件事之外的所有錯誤,清除代碼中缺少的已分配內存。

s =  malloc(10);

這一行分配了 10 個字節,而不是 10 個指針! 一個指針存儲在幾個字節上,在今天的架構中通常是 4 或 8 個字節。

改為這樣做:

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

s = malloc(10); 為您保留 10 個字節的內存,但您需要足夠的內存來容納 10 個指針。 你應該使用

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

編輯:對不起,你是對的,它應該是 char* 而不是 int,我的錯誤

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM