【发布时间】:2019-07-18 20:13:40
【问题描述】:
我刚刚开始学习一些 C 语言,所以我编写了一个小程序来练习使用 char 数组。
它从stdin 中获取一个字符串,并在删除尾随空格和空行后打印它(如果你们中的任何人有“C 编程语言”的第二版,那就是问题 1-18)。
然而,在按下 EOF 键结束输入后,程序退出并出现错误:'Segmentation fault (core dumped)'。
我已经使用Wall、Wextra、Werror 和g 进行了编译,但在编译时没有显示错误(在 Fedora 30 上使用 gcc 9.1.1)。
我也通过gdb运行程序,发现导致故障的行是这一行:
for (; (c = input[start + i]) != '\n' || c != '\0'; ++i)
我正在粘贴整个文件,因为它是一个简短的程序,一切都可能是导致错误的原因。
#include <stdio.h>
#define MAX 100
int Read(char input[], int max);
void ProcessInput(char input[], char output[], int length);
int GetToEndLine(char input[], char outLine[], int startIndex);
int main(void){
char input[MAX];
char output[MAX];
int length;
printf("W: Max output is of %d chars.\n", MAX - 1);
length = Read(input, MAX);
ProcessInput(input, output, length);
printf("\nCleaned input:\n---\n%s\n---\n", output);
return 0;
}
int Read(char input[], int max){
int i, c;
for (i = 0; (c = getchar()) != EOF && i < max - 1; ++i)
input[i] = c;
input[i] = '\0';
return i;
}
void ProcessInput(char input[], char output[], int length){
int mainIndex = 0,
new_mainIndex = 0,
outputIndex = 0;
char line[MAX];
while ((length - mainIndex) > 0){
new_mainIndex = GetToEndLine(input, line, mainIndex);
if (new_mainIndex == mainIndex){
++mainIndex;
continue;
}
for (int j = new_mainIndex - mainIndex;
line[j] == ' ' || line[j] == '\t' || line[j] != '\n'; --j)
line[j] = '\0';
for(int j = 0; line[j] != '\0'; ++j, ++outputIndex)
output[outputIndex] = line[j];
output[outputIndex] = '\n';
++outputIndex;
mainIndex = new_mainIndex + 1;
}
}
int GetToEndLine(char input[], char line[], int start){
int c,
i = 0;
for (; (c = input[start + i]) != '\n' || c != '\0'; ++i)
line[i] = c;
line[i] = c;
return start + i;
}
成功的测试运行的完整输出应该是:
W: Max output is of 99 chars.
asdf
asdf
Cleaned Input:
---
asdf
asdf
---
我得到的是:
W: Max output is of 99 chars.
asdf
asdfSegmentation fault(core dumped)
有人可以帮我调试这个程序吗?
【问题讨论】:
-
崩溃发生时,所有涉及的变量的值是多少?他们看起来神志清醒吗?没有越界索引?
-
我不知道段错误,但表达式
a != X || a !=Y对每个不相等的X和Y都是正确的 -
@EugeneSh。我认为你在那里做了一些事情,for 循环需要是 && 而不是 ||。连续循环可能是段错误,因此当它超过输入+1的长度时,给他一个超出范围的索引。
-
建议使用
strchrnul(str, '\n'); -
@plum0 我一点也不困惑。我正在确认您的“可能”是“最肯定是”。我也不会说这是唯一的问题,但那绝对会导致无限循环,最终会破坏该数组并调用 UB。