用户输入字符串到数组中,导致缓冲区溢出
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 ) ;
但是因为长度是硬编码在字符串中并且与 i
或 ARRAY_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 ) ;
我是 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 ) ;
但是因为长度是硬编码在字符串中并且与 i
或 ARRAY_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 ) ;