这可能看起来很傻,但我不明白发生了什么......
#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
�@
�@
�@
�@
�@
�@
答案 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,我的错误