说我有代码:
char* word = malloc (sizeof(char) * 6);
strcpy(word, "hello\0extra");
puts(word);
free(word);
这个编译只是发现和Valgrind没有问题,但实际上有问题吗?好像我写入了我不拥有的记忆。
另外,一个单独的问题,但是当我用
之类的东西填充我的缓冲区时char* word = malloc (sizeof(char) * 6);
strcpy(word, "1234567\0");
puts(word);
free(word);
它打印出1234567并且Valgrind确实遇到了问题。做这样的事情有什么后果?它似乎每次都有效。如果这是错误的,请纠正我,但根据我的理解,另一个程序可以将记忆带过6并写入其中。如果发生这种情况,打印这个词会永远继续下去,直到遇到一个空字符?在学习C字符串时,这个角色让我感到很困惑。
答案 0 :(得分:2)
第一个strcpy没关系
strcpy(word, "hello\0extra");
您创建一个char
数组常量并将指针传递给strcpy
。复制所有字符(包括第一个\ 0),忽略余数。
但是等等......你有一些额外的角色。这使得const数据部分更大一些。在嵌入式环境中,闪存空间很少是一个问题。但是没有运行时问题。
答案 1 :(得分:0)
strcpy(word, "hello\0extra");
这是有效的,因为第二个参数应该是格式良好的字符串,这是因为你的第6个字符\0
形成一个长度为5的字符串。
strcpy(word, "1234567\0");
在这里,您正在访问您不拥有/分配的内存,因此这是一次访问冲突并可能导致崩溃。(seg fault)
答案 2 :(得分:0)
首次拨打strcpy
时,NUL
会插入字符串的中间位置。这意味着处理以null结尾的字符串的函数会将您的字符串视为以第一个NUL
停止,并忽略字符串的其余部分。但是,free
将释放所有这些并且valgrind不会报告问题,因为malloc
将在分配表中存储缓冲区的长度,free
将使用该条目来确定有多少要释放的字节数。换句话说,malloc
和free
并不意味着处理以null结尾的字符串,因此字符串中间的NUL
不会影响它们。相反,free
根据您在第一个位置分配的字节数来确定字符串的长度。
使用第二个示例,溢出由malloc
分配的缓冲区的末尾。结果未定义。从理论上讲,您写入的内存可能已经被另一个malloc
调用分配,但在您的示例中,缓冲区后内存没有任何内容,因此它是无害的。字符串处理函数将您的字符串视为以第一个NUL
结尾,而不是malloc
分配的缓冲区的结尾,因此打印出所有字符串。
答案 3 :(得分:0)
你的第一个问题已经有了几个好的答案。关于你的第二个问题,关于在你的malloced内存结束后写一个字节的后果:
将6个字节写入并将7写入其中会导致崩溃是值得怀疑的。 malloc
喜欢在某些边界上对齐内存,因此不太可能在页面末尾给你六个字节,这样在字节7处就会出现访问冲突。但是如果你malloc
65536字节并尝试写入结束,您的程序可能会崩溃。写入无效内存会在很多时候起作用,这会使调试变得棘手,因为只有在某些情况下才会出现随机崩溃。