我有一些代码给你,希望有人能告诉我,我错了.目前我正在将我的编程难题移植到其他编程语言中,以便获得一些动手.
C中的代码抽象(更新):
#include#include #include 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); } }
代码运行得很好,直到我取消注释dosomething()方法中的free()调用.这就是我不理解的.正如我所看到的,释放内存绝对没有问题,因为在从递归调用返回后不再使用它,但是programm输出告诉了不同的东西.
没有免费的输出符合预期:
... 1_34567890 1_34567890 ...
使用第二个空闲时,只有一个结果,而程序停止时:
*** Error in `./a.out': malloc(): memory corruption (fast): 0x000000000164e0d0 *** Abgebrochen (Speicherabzug geschrieben)
更新:我根据评论和答案更改了代码,但问题仍然存在.如果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)
任何人都可以向我解释一下,我在眨眼间的是什么?
Update2:@Michi和@MichaelWalz已经解决了这个问题.它是使用malloc之间的组合 - 因此在第一次迭代后处理内存中的垃圾(打印内存地址以及字符串显示非常整洁),并使用strcat.
在未初始化的内存上使用strcat会将内存中的字符串追加到内存中指针后面的下一个"\ 0"字符.如果内存未初始化,则可能远远超出该字符串的范围.
感谢你们!
工作代码:
#include#include #include 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); } }
Ring Ø.. 9
原因是因为malloc函数分配10个字符而需要11个字符(结束\0
).
虽然这是依赖于实现的,但是高效的malloc函数可能使用分配区域内外的一些字节来设置一些内部信息.在此内部区域被更改(一个char太多)之后,free可以使用这些字节,最终结果是未定义的行为.
无论如何,更改甚至读取数组越界是 UB.
更好用
char *s = malloc(strlen(dummy) + 1);
并且不要强制生成malloc的结果指针.
原因是因为malloc函数分配10个字符而需要11个字符(结束\0
).
虽然这是依赖于实现的,但是高效的malloc函数可能使用分配区域内外的一些字节来设置一些内部信息.在此内部区域被更改(一个char太多)之后,free可以使用这些字节,最终结果是未定义的行为.
无论如何,更改甚至读取数组越界是 UB.
更好用
char *s = malloc(strlen(dummy) + 1);
并且不要强制生成malloc的结果指针.