我试图编写一个C99程序(如果可能的话,没有GNU扩展名)需要从任意长度的用户那里获取输入。这是我到目前为止的内容,它使SEGFAULT-ing保持在第26行。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
int get_line(char* buffer, FILE* fp) {
int bufread = 0;
int bufsize = LINE_MAX;
if(buffer == NULL) {
buffer = (char*)malloc(sizeof(char)*bufsize);
strcpy(buffer, "");
}
while(true) {
if(bufread == bufsize) {
bufsize += LINE_MAX;
buffer = (char*)realloc(buffer, sizeof(char)*bufsize);
}
char character = fgetc(fp);
if(character == '\n') {
break;
} else {
strcat(buffer, character);
bufread += 1;
}
}
return bufread;
}
int main() {
printf("Enter a string: ");
char* string = NULL;
int chars_read = get_line(string, stdin);
printf("The number of chars read is %d\n", chars_read);
printf("The string you entered was %s\n", string);
return 0;
}
答案 0 :(得分:1)
在get_line
buffer = (char*)malloc(sizeof(char)*bufsize); strcpy(buffer, "");
执行 strcpy 只是将第一个字符设置为0是一种复杂的方法,只需执行*buffer = 0;
。
sizeof(char)
根据定义为1
您不需要进行投射
还请注意,如果 buffer 在参数中未设置为NULL,则该行为很危险,并且由于代码假定给定的缓冲区至少具有LINE_MAX
字符而无法定义。
在
char character = fgetc(fp);
您无法检测到EOF,需要为 int
在
if(character == '\n') { break;
您错过了检测EOF的机会
您错过了 while
之后的 buffer 末尾添加空字符的操作在
strcat(buffer, character);
这是无效的,因为 strcat 的第二个参数必须是char*
, strcat 连接两个字符串,而不是带有字符的字符串
假设有一个 strcat 可以附加一个字符,每次搜索字符串的末尾以附加字符时,只需使用 bufread 即可,索引
因为该功能的配置文件是
int get_line(char* buffer, FILE* fp) {
当您退出get_line
时,您丢失了 buffer 的当前值,造成了内存泄漏,并在 main printf("The string you entered was %s\n", string);
中打印了空指针。为了避免这种情况,您可以将字符串作为输出参数,让您仍然返回新的长度:
提案:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
size_t get_line(char ** buffer, FILE* fp) {
size_t bufsize = LINE_MAX;
size_t bufread = 0;
*buffer = malloc(bufsize);
if (*buffer == NULL)
return 0;
while (true) {
if (bufread == bufsize) {
bufsize += LINE_MAX;
*buffer = realloc(*buffer, bufsize);
}
int character = fgetc(fp);
if ((character == '\n') || (character == EOF)) {
(*buffer)[bufread] = 0;
/* note you can do : *buffer = realloc(*buffer, bufread + 1); to only use the needed memory */
return bufread;
}
(*buffer)[bufread++] = character;
}
}
int main() {
printf("Enter a string: ");
char * string = NULL;
size_t chars_read = get_line(&string, stdin);
if (string != NULL) {
printf("The number of chars read is %zu\n", chars_read);
printf("The string you entered was '%s'\n", string);
free(string);
}
}
编译和执行:
pi@raspberrypi:/tmp $ gcc -pedantic -Wextra p.c
pi@raspberrypi:/tmp $ ./a.out
Enter a string: is it working ?
The number of chars read is 15
The string you entered was 'is it working ?'
pi@raspberrypi:/tmp $ ./a.out
Enter a string:
The number of chars read is 0
The string you entered was ''
在 valgrind 下:
pi@raspberrypi:/tmp $ valgrind ./a.out
==20382== Memcheck, a memory error detector
==20382== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==20382== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==20382== Command: ./a.out
==20382==
Enter a string: what about memory leak ?
The number of chars read is 24
The string you entered was 'what about memory leak ?'
==20382==
==20382== HEAP SUMMARY:
==20382== in use at exit: 0 bytes in 0 blocks
==20382== total heap usage: 3 allocs, 3 frees, 4,096 bytes allocated
==20382==
==20382== All heap blocks were freed -- no leaks are possible
==20382==
==20382== For counts of detected and suppressed errors, rerun with: -v
==20382== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)