【发布时间】:2021-10-08 16:01:15
【问题描述】:
我对动态二维字符数组的 C 代码有疑问:malloc 缓冲区溢出。程序的思路是初始化一个全局的二维字符数组,程序运行时,输入一些单词,保存到那个二维字符数组中。我不熟悉 realloc 函数。这里有什么问题?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char **array_history;
int count = 0;
#define MAX_LINE_CHARS 1024
int main (void){
array_history = malloc(sizeof(char *));
while (1) {
char line[MAX_LINE_CHARS];
if (fgets(line, MAX_LINE_CHARS, stdin) == NULL)
break;
array_history = realloc(array_history, sizeof(char*)*(count + 1));
int len_size = strlen(line) + 1;
array_history[count] = malloc(len_size*sizeof(char));
for (int i = 0; line[i] != '\0'; i++) {
array_history[count][i] = line[i];
// printf("%c", line[i]);
}
// printf("%s", array_history[0]);
// for (int i = 0; history[i] != NULL; i++) {
// printf("%s\n", history[i]);
// }
count++;
}
for (int i = 0; array_history[i] != NULL; i++) {
printf("%s", array_history[i]);
}
return 0;
}
【问题讨论】:
-
array_history[i] != NULL你认为这个哨兵NULL会来自哪里?通过malloc或realloc获得的内存不需要初始化。由你决定。您也没有任何关于NULL值的内存。你只为你读入的行分配内存。 -
for (int i = 0; array_history[i] != NULL; i++),这一步我要打印array_history
-
我知道,但你为什么认为会有一个数组元素持有
NULL指针?如果没有这样的数组元素,您的代码将愉快地遍历所有可以访问的内存并访问不允许访问的位置。 -
另外:你不应该使用这种模式:
array_history = realloc(array_history, ...。如果出现错误realloc将返回NULL,并且您无法再访问之前拥有的内存位置。这包括无法释放该内存的方法。在分配给您传递给realloc的指针之前,请始终使用一些临时变量并检查NULL。 -
您也未能终止您的字符串:
for (int i = 0; line[i] != '\0'; i++)这不会复制0字节。你为什么不为此目的使用strcpy或strdup或类似名称?