虽然代码正在编译并正确显示输出,但是当我运行" valgrind"时,它显示以下错误。我很难理解这一点,因为我没有valgrind的任何背景。
Invalid write of size 1
==14657== at 0x4EAE10C: _IO_default_xsputn (genops.c:480)
==14657== by 0x4E7CF81: vfprintf (vfprintf.c:1630)
==14657== by 0x4EA3813: vsprintf (iovsprintf.c:43)
==14657== by 0x4E85A06: sprintf (sprintf.c:34)
==14657== by 0x400622: copy_id_name (assign2a.c:12)
==14657== by 0x40065E: main (assign2a.c:21)
==14657== Address 0x51f204b is 0 bytes after a block of size 11 alloc'd
==14657== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14657== by 0x400600: copy_id_name (assign2a.c:11)
==14657== by 0x40065E: main (assign2a.c:21)
==14657==
请解释实际错误以及删除此错误的解决方案。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/** Returns a pointer to allocated memory containing string in form "<id>=<name>" */
char *copy_id_name(const char *id, const char *name) {
char *ptr = NULL;
size_t len;
// Compute required length
len = strlen(id) + strlen(name); // [sic]
ptr = malloc(len-2); // [sic]
sprintf(ptr, "%s=%s", id, name);
return ptr;
}
int main(int argc, char *argv[])
{
char *ptr;
if (argc > 2) {
ptr = copy_id_name(argv[1], argv[2]);
} else {
ptr = copy_id_name("666", "badname");
}
printf("result: [%s]\n", ptr);
return 0;
}
答案 0 :(得分:3)
首先,您必须记住C中的字符串实际上比strlen
报告的字符长一个字符。该额外字符用于特殊字符('\0'
),告诉函数它是字符串的结尾。
这里的问题是你要分配两个字节 less 而不是id
和name
字符串的总长度,然后你将这些字符串与两个添加了字符('='
和终止'\0'
)。这意味着你将超出分配内存的末尾。
答案 1 :(得分:2)
ptr = malloc(len-2);
您分配的所需内容少于4个字节。 strlen()给出字符串的长度,不计算null终止。但是,您需要为空终止分配空间。只需将-2更改为+2。