[英]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.