用户输入字符串到数组中,导致缓冲区溢出

User-input string into array, causing buffer overflow

我是 C 的新手,我现在正在开发一个程序,要求用户以程序名称的形式输入字符数组(字符串),将这些名称存储在一个数组中,然后传递这个数组到另一个函数。

现在,我尝试实现此目的的最新方法是使用动态分配的数组,因为我不知道用户可能想要输入什么,我是这样做的:

char *process;
process = (char *)malloc(sizeof(char) * (i+1));

然后我继续请求用户输入并使用 printf:

确认他们的输入
printf("Enter process name: ");
scanf("%79s", &process); // take input, load into array
// fgets(process, sizeof(ARRAY_SIZE), stdin);
printf("You entered: %s\n", process[i]);

我已经尝试了 scanf()fgets(),其中 scanf() 确实有效并且 fgets() 导致程序完全跳过我的 printf 语句然后继续:

for(i = 0; i < ARRAY_SIZE; i++)
    printf("process = %s\n", process[i]);

这是程序以 Segmentation Fault 终止的地方。我知道这是由于用户输入超出了分配的缓冲区。

gdb中打印process的值时,它充满了垃圾(根据我的理解,这是C如何在添加值之前初始化数组)。在 scanf("%79s", &process) 之后,进程显示我的输入被添加到垃圾的开头而不是替换垃圾。我的问题是如何 "empty" 我的数组,以便我停止溢出缓冲区?三天来尝试了几种方法,我认为这与我缺少有关如何正确初始化数组的一些细节有关。我有 #define ARRAY_SIZE 80 应该足以实现此功能,但在以后的实现中可能还不够。

非常感谢任何帮助。

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *process;
    int i = 0;//number of input character;
    size_t size;//Allocated size
    int ch;

    //process = (char *)malloc(sizeof(char) * (i+1));//+1 for '[=10=]'
    size = 16;//Initial size
    process = malloc(size);//cast don't need in C

    printf("Enter process name: ");//fflush(stdout);
    while((ch = getchar())!=EOF && ch != '\n'){
        if(i == size -1){//-1 for NUL('[=10=]')
            char *temp = realloc(process, size += 16);//expand size
            if(temp==NULL){
                fprintf(stderr, "failed to malloc\n");
                free(process);
                exit(EXIT_FAILURE);
            }
            process = temp;//successfully extended update
        }
        process[i++] = ch;
    }
    process[i] = 0;
    printf("process = %s\n", process);//type of process[i] is `char`
    free(process);
    return 0;
}

变量 process 已经是一个指针,&process 的类型为 char** 并且是指向指针变量的指针,而不是指向已分配缓冲区的指针。

sizeof(char) 根据定义总是等于 1,因此在 malloc() 调用中是不必要的。如果你使用 scanf() 它应该是这样的:

scanf( "%79s", process ) ;

但是因为长度是硬编码在字符串中并且与 iARRAY_SIZE 无关,所以最好使用 fgets(),但是你使用长度参数 sizeof(ARRAY_LEN)sizeof(int) 相同;你的意思只是 ARRAY_LEN。在这种情况下,分配不必是 i + 1 因为 fgets() 在给定的大小内插入 nul,所以:

fgets( process, ARRAY_SIZE, stdin ) ;

此外,对于定长数组几乎没有必要使用malloc();您不是将数组设置为适合输入,而是限制输入以适合数组。既然如此我建议:

char process[ARRAY_SIZE] ;
printf( "Enter process name: " ) ;
fgets( process, sizeof(process), stdin ) ;

对于输入数据的逐字符输出,需要%c格式说明符,而不是%s:

for( i = 0; i < ARRAY_SIZE; i++ )
    printf( "process = %c\n", process[i] ) ;

但这将从数组中打印未使用的、未初始化的字符,因此更有可能:

for( i = 0; process[i] != '[=14=]'; i++ )
    printf( "process = %c\n", process[i] ) ;

或者因为 process 是一个以 nul 结尾的字符串,简单地:

printf("process = %s\n", process ) ;

所以最终你需要的是:

char process[ARRAY_SIZE] ;
printf( "Enter process name: " ) ;
fgets( process, sizeof(process), stdin ) ;
printf("process = %s\n", process ) ;