fputs 上的分段错误
Segmentation Fault on fputs
总的来说,我对 C 和内存分配还很陌生。基本上我想做的是复制一个未知大小的输入文件的内容并使用递归反转它的内容。我觉得我非常接近,但是当我尝试放入我认为是文件反转内容的内容时,我一直遇到分段错误(我认为是因为我认为我做对了...... )
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int recursive_back(char **lines, int lineNumber, FILE *input) {
char *input_line = malloc(sizeof(char) * 1000);
lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));
if(fgets(input_line, 201, input) == NULL) {
*(lines + lineNumber) = input_line;
return 1;
}
else {
printf("%d\n", lineNumber);
return (1+recursive_back(lines, ++lineNumber, input));
}
}
void backward (FILE *input, FILE *output, int debugflag ) {
int i;
char **lines; //store lines in here
lines = malloc(1000 * sizeof(char *) ); //1000 lines
if(lines == NULL) { //if malloc failed
fprintf(stderr, "malloc of lines failed\n");
exit(1);
}
int finalLineCount, lineCount;
finalLineCount = recursive_back(lines, 0, input);
printf("test %d\n", finalLineCount);
for(i = finalLineCount; i > 0; i--) {
fputs(*(lines+i), output); //segfault here
}
}
我正在使用一个简单的输入文件来测试代码。我的输入文件有 6 行,上面写着 "This is a test input file"。实际输入文件在另一个函数中打开并传递给后向函数。我已经验证了我程序中的其他功能,因为我一直在尝试不同的选项。这两个功能是我遇到麻烦的唯一功能。我做错了什么?
你的问题在这里:
lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));
正如@ooga 所说。它至少存在三个不同的问题:
你正在重新分配recursive_back()
的局部变量lines
指向的内存块,并存储新地址(假设重新分配成功)返回到该局部变量。新位置不一定与旧位置相同,但指向它的唯一指针是在 recursive_back()
末尾超出范围的局部变量。调用者对应的变量没有改变(包括调用者是recursive_back()
本身),因此在recursive_back()
returns.[=25=之后不能再依赖为有效指针]
您使用错误的类型分配 space。 lines
的类型为 char **
,因此它指向的对象的类型为 char *
,但您是根据 char
的大小保留 space。
您没有预留足够的 space,至少在第一次调用时,当 lineNumber
为零时。在该调用中,当请求的 space 正好是零字节时,realloc()
的作用是 释放 lines
指向的内存。在随后的调用中,分配的 space 总是比您认为分配的少一行。
如果您可以依赖最多 1000 行的输入,那么 realloc()
似乎完全没有必要,因此您应该考虑将其删除。如果您真的需要能够以调用者将看到的方式重新分配,那么调用者需要将 pointer 传递给它的变量,以便 recursive_back()
可以修改它通过那个指针。
总的来说,我对 C 和内存分配还很陌生。基本上我想做的是复制一个未知大小的输入文件的内容并使用递归反转它的内容。我觉得我非常接近,但是当我尝试放入我认为是文件反转内容的内容时,我一直遇到分段错误(我认为是因为我认为我做对了...... )
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int recursive_back(char **lines, int lineNumber, FILE *input) {
char *input_line = malloc(sizeof(char) * 1000);
lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));
if(fgets(input_line, 201, input) == NULL) {
*(lines + lineNumber) = input_line;
return 1;
}
else {
printf("%d\n", lineNumber);
return (1+recursive_back(lines, ++lineNumber, input));
}
}
void backward (FILE *input, FILE *output, int debugflag ) {
int i;
char **lines; //store lines in here
lines = malloc(1000 * sizeof(char *) ); //1000 lines
if(lines == NULL) { //if malloc failed
fprintf(stderr, "malloc of lines failed\n");
exit(1);
}
int finalLineCount, lineCount;
finalLineCount = recursive_back(lines, 0, input);
printf("test %d\n", finalLineCount);
for(i = finalLineCount; i > 0; i--) {
fputs(*(lines+i), output); //segfault here
}
}
我正在使用一个简单的输入文件来测试代码。我的输入文件有 6 行,上面写着 "This is a test input file"。实际输入文件在另一个函数中打开并传递给后向函数。我已经验证了我程序中的其他功能,因为我一直在尝试不同的选项。这两个功能是我遇到麻烦的唯一功能。我做错了什么?
你的问题在这里:
lines = realloc(lines, (lineNumber) * 1000 * sizeof(char));
正如@ooga 所说。它至少存在三个不同的问题:
你正在重新分配
recursive_back()
的局部变量lines
指向的内存块,并存储新地址(假设重新分配成功)返回到该局部变量。新位置不一定与旧位置相同,但指向它的唯一指针是在recursive_back()
末尾超出范围的局部变量。调用者对应的变量没有改变(包括调用者是recursive_back()
本身),因此在recursive_back()
returns.[=25=之后不能再依赖为有效指针]您使用错误的类型分配 space。
lines
的类型为char **
,因此它指向的对象的类型为char *
,但您是根据char
的大小保留 space。您没有预留足够的 space,至少在第一次调用时,当
lineNumber
为零时。在该调用中,当请求的 space 正好是零字节时,realloc()
的作用是 释放lines
指向的内存。在随后的调用中,分配的 space 总是比您认为分配的少一行。
如果您可以依赖最多 1000 行的输入,那么 realloc()
似乎完全没有必要,因此您应该考虑将其删除。如果您真的需要能够以调用者将看到的方式重新分配,那么调用者需要将 pointer 传递给它的变量,以便 recursive_back()
可以修改它通过那个指针。