以下程序查找并删除以相同字符开头和结尾的单词。它工作得很好,除了我决定从 deleteWords()
中获取用于打印结果文本的代码并将其放在 main()
中。因此,*fpOut
参数在deleteWords()
中变得多余。删除参数结果为
/bin/sh: line 1: 1371 Segmentation fault: 11 ./main duom.txt rez.txt make: *** [main] 错误 139
但是,如果我编译它并运行它的任何第三个参数(例如 int useless
参数而不是 FILE *fpOut
),它可以正常工作。
有没有人知道是什么导致了这个问题?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int checker (char zodis[]) {
size_t last = strlen(zodis);
if (zodis[0] == zodis[last-1])
return 0;
return 1;
}
void memAlloc (char **text, char **buffer, FILE **fp, char *fileName) {
int fileLength;
*fp = fopen(fileName, "r");
fseek(*fp, 0L, SEEK_END);
fileLength = fseek(*fp, 0L, SEEK_SET);
*text = malloc(fileLength * sizeof(char));
*buffer = malloc(fileLength * sizeof(char));
}
void deleteWords (FILE *fp, int anyUselessParameter, char *buffer) {
char *text;
while (fscanf(fp, "%s", text) == 1) {
if (checker(text)) {
printf("%s ", text);
sprintf(buffer + strlen(buffer), "%s ", text);
}
}
printf("\n");
}
int main(int argc, char *argv[]) {
FILE *fp, *fpOut;
int anyUselessParameter;
char *text, *buffer, *inputFileName = argv[1], *outputFileName = argv[2];
if (argc < 2)
return 0;
fpOut = fopen(outputFileName, "w");
memAlloc(&text, &buffer, &fp, inputFileName);
deleteWords(fp, anyUselessParameter, buffer);
fputs(buffer, fpOut);
fclose(fp);
fclose(fpOut);
free(text);
return 0;
}
最佳答案
char *text;
while (fscanf(fp, "%s", text) == 1) {
scanf
需要分配缓冲区。在这里它取消引用一个未初始化的指针 text
并写入它。 scanf
尝试写入 text[0]
、text[1]
.. 等等,因此访问文本越界和未定义行为发生。
*buffer = malloc(fileLength * sizeof(char));
...
sprintf(buffer + strlen(buffer), "%s ", text);
buffer
未初始化,因此 strlen(buffer)
将产生一些未定义的值。如果您希望稍后使用 strlen,请显式初始化 buffer[0] = '\0'
。此外,您不包括用于在缓冲区内终止 '\0'
字符的内存。
当您尝试将文件读入缓冲区时,缓冲区是使用文件大小分配的
if (fread(buffer, fileLenght, 1, fp) != fileLength) { /* handle error */ }
如果必须,请使用 snprintf
而不是 sprintf
以确保安全。 snprinttf(buffer+strlen(buffer), fileLength - strlen(buffer), ...);
此外,如果没有在 %s
修饰符中指定字段长度,请尽量不要使用 scanf
。你可以试试:
char text[256]; // or other maximum word length
while (fscanf(fp, "%255s", text) == 1) {
因为您已经为文件分配了内存,所以如果必须的话,您可以将它用作 scanf 的参数。需要为 scanf 准备格式字符串作为参数——这有点困难。见下文:
for (;;) {
// prepare scanf %s format modifier to use with printf to write to buffer end
char fmt[20];
size_t buffer_size = fileLenght;
size_t free_in_buffer = buffer_size - strlen(buffer);
snprintf(fmt, 20, "%%%ds", free_in_buffer);
// we will write here: up to free_in_buffer
char *in = buffer + strlen(buffer);
if (fscanf(fp, fmt, in) != 1) break;
// we now check the last readed word form the file
if (!checker(in)) {
// if the last readed word is bad, we can revert it
in[0] = '\0'
}
}
关于c - 删除冗余参数会导致段错误,似乎无缘无故,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53636538/