在下面的代码中,我遇到了分段错误 但是当我在printf的末尾添加一个\ n时(“*我开始学习C !! \ n ”);它解决了这个问题。有什么想法吗?
#include <stdio.h>
#include <string.h>
char* draw_line(int line_len, const char style) {
int i;
char *line;
char s_style[2] = {style, '\0'};
strcpy(line, "\n");
for(i=0; i<line_len; i++) {
strcat(line, s_style);
}
printf("%s\n", line); //debug
return line;
}
int main() {
char *line;
printf ("* I started to learn C!! ");
line = draw_line(5, '*');
// printf("%s\n", line);
return 0;
}
答案 0 :(得分:1)
至少这些行是一个问题(不是中间问题,只是将其保留在上下文中):
char *line;
char s_style[2] = {style, '\0'};
strcpy(line, "\n");
此处line
未初始化,这意味着它将在堆栈中存储line
的位置。然后这个“随机”地址由strcpy
获取,它在那里复制那个双字节字符串。
如果地址位于您不允许写入的位置,您很幸运,您的程序崩溃时出现分段错误,调试程序会显示堆栈跟踪中的问题行。
但是,如果地址恰好是可写存储器位置,那么无论何处写入都会被写入。然后会发生什么,所有的赌注都没有了。它可能是未使用的内存,没有任何反应。它可能是一些文本,你只会在某处获得损坏的文本,它可能是一些重要的变量,它将使你的程序行为有趣。它可能是堆栈中的返回地址,导致程序在跳转到损坏的地址时执行完全意外的操作。堆栈可以从前面的函数调用和局部变量中获得所有类型的值,因此地址甚至可能包含来自其他指针的值。
但问题是,当您更改代码时,无论如何,堆栈中剩余的值以及未初始化的变量都会发生变化,因此任何更改都会使您的代码行为不同。这可能是您添加printf
时发生的情况。
简单地说,不要那样做。取消引用未初始化的变量是未定义的行为。
为了避免这样的许多错误,请为编译器启用警告并修复它们(对于 gcc 和 clang ,命令行开关-Wall -Wextra
是一个很好的组合任何新代码。)