我有一些代码需要你翻译,希望有人能告诉我哪里出了问题。目前,我正在将我的编程难题移植到其他编程语言中,以便更好的实践。
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);
}
}
代码执行良好,直到我取消dosomething()方法中的free()调用。这就是我不理解的地方。在我的看来,在递归调用返回后,释放内存绝对没有问题,因为它已经不再使用,但程序的输出结果却不同。
没有free的输出结果如预期:
...
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)
请问有人能解释一下我看到的闪烁是什么吗?
更新2:
@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);
}
}
malloc
等函数的结果转换为其他类型。 - too honest for this sitens = strcat( ns, &s[2] )
中需要赋值?只有strcat
就足够了 - 可以查看函数说明。此外,&s[2]
与s + 2
是相同的(我发现这种语法更短)。 - i486dosomething
函数内忘记了使用free
释放内存;建议使用valgrind进行检查,并使用所有警告和调试信息进行编译(gcc -Wall -Wextra -g
)。 - Basile Starynkevitchmalloc(sizeof(char)*11);
更改为malloc(11);
,因为sizeof(char)==1
,这意味着您的代码看起来像这样:malloc(1 * 11)
。 - Michi