Oli*_*ich 3 c recursion pointers
我有一些代码给你,希望有人能告诉我,我错了.目前我正在将我的编程难题移植到其他编程语言中,以便获得一些动手.
C中的代码抽象(更新):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *dummy = "1234567890";
const char* inlet = "_";
void dosomething(int c, char* s){
printf("%s\n", s);
if (c < 10) {
char *ns = malloc(sizeof(char)*11);
strncpy(ns, s, c-1);
strncat(ns, inlet, 1);
strcat(ns, &s[c]);
dosomething(c+1, ns);
//free(ns);
}
}
void main() {
for(int i = 0; i < 100; i++) {
char *s = malloc(sizeof(char)*11);
strcpy(s, dummy);
dosomething(1, s);
free(s);
}
}
Run Code Online (Sandbox Code Playgroud)
代码运行得很好,直到我取消注释dosomething()方法中的free()调用.这就是我不理解的.正如我所看到的,释放内存绝对没有问题,因为在从递归调用返回后不再使用它,但是programm输出告诉了不同的东西.
没有免费的输出符合预期:
...
1_34567890
1_34567890
...
Run Code Online (Sandbox Code Playgroud)
使用第二个空闲时,只有一个结果,而程序停止时:
*** Error in `./a.out': malloc(): memory corruption (fast): 0x000000000164e0d0 ***
Abgebrochen (Speicherabzug geschrieben)
Run Code Online (Sandbox Code Playgroud)
更新:我根据评论和答案更改了代码,但问题仍然存在.如果dosomething()方法中的free()调用是错误的,则使用malloc分配更多内存不会阻止内存错误.输出被正确地产生用于递归的第一次迭代,第二显示不同的结果,在第三以及然后程序失败(参见关于新的结果的函数的顶部上的新的printf:
输出:
1234567890
_234567890
__34567890
___4567890
____567890
_____67890
______7890
_______890
________90
_________0
1234567890
@@J_234567890
@@J_J_234567890
@@J__J_234567890
@@J___J_234567890
@@J___J_234567890
@@J___J_234567890
@@J____J_234567890
@@J____J_234567890
@@J_____0__234567890
1234567890
@@J_234567890
@@J_J_234567890
@@J__J_234567890
@@J___J_234567890
@@J___J_234567890
@@J___J_234567890
@@J____J_234567890
@@J____J_234567890
@@J_____0__234567890__234567890
*** Error in `./a.out': free(): invalid next size (fast): 0x00000000014a4130 ***
Abgebrochen (Speicherabzug geschrieben)
Run Code Online (Sandbox Code Playgroud)
任何人都可以向我解释一下,我在眨眼间的是什么?
Update2:@Michi和@MichaelWalz已经解决了这个问题.它是使用malloc之间的组合 - 因此在第一次迭代后处理内存中的垃圾(打印内存地址以及字符串显示非常整洁),并使用strcat.
在未初始化的内存上使用strcat会将内存中的字符串追加到内存中指针后面的下一个"\ 0"字符.如果内存未初始化,则可能远远超出该字符串的范围.
感谢你们!
工作代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *dummy = "1234567890";
const char* inlet = "_";
void dosomething(int c, char* s){
printf("%p %s\n", s, s);
if (c < 10) {
//char *ns = malloc(sizeof(char)*11);
char *ns = calloc(11, sizeof(char));
strncpy(ns, s, c);
strncat(ns, inlet, 1);
strncat(ns, &s[c+1],10-c);
dosomething(c+1, ns);
free(ns);
}
}
void main() {
for(int i = 0; i < 100; i++) {
//char *s = malloc(sizeof(char)*11);
char *s = calloc(11, sizeof(char));
strcpy(s, dummy);
dosomething(0, s);
free(s);
}
}
Run Code Online (Sandbox Code Playgroud)
原因是因为malloc函数分配10个字符而需要11个字符(结束\0).
虽然这是依赖于实现的,但是高效的malloc函数可能使用分配区域内外的一些字节来设置一些内部信息.在此内部区域被更改(一个char太多)之后,free可以使用这些字节,最终结果是未定义的行为.
无论如何,更改甚至读取数组越界是 UB.
更好用
char *s = malloc(strlen(dummy) + 1);
Run Code Online (Sandbox Code Playgroud)
并且不要强制生成malloc的结果指针.
小智 5
malloc()通常不会初始化分配的内存。您应该使用memset()初始化分配的内存或使用calloc()它使用零初始化分配的内存。
您应该为 11 个字符('\0' 为 10 + 1)分配内存,并且不要将malloc().
在某些系统上,您可以配置 malloc 来初始化内存,但这充其量只是一个糟糕的调试帮助,您永远不要指望它。
| 归档时间: |
|
| 查看次数: |
2214 次 |
| 最近记录: |