我写了下面的c函数来获取用户的字符串。它使用realloc动态更改char数组大小以适应未知的char数组长度。根据我的理解,它应该能够获取尽可能多的输入(或者有内存可用),但是,当我尝试从随机文本文件中管道文本时(使用“tr'\ n''' './random.txt“以确保我从文本文件中删除了任何换行符),我得到”无法分配内存来保存char数组。退出!“错误信息。为什么会这样?我的阵列是否能够容纳数千兆字节的数据,因为我有16 GB的RAM用于动态增长的方式?
#include <stdio.h>
#include <stdlib.h>
void GetString(int*, int*);
int main(void)
{
unsigned int strLength = 32;
char *stringPtr = malloc(strLength);
if (stringPtr == NULL)
{
fprintf(stderr, "Unable to allocate memory to hold char array. Exiting!\n");
return 1;
}
printf("Enter some input: ");
int c = EOF;
unsigned int i = 0;
while ((c = getchar()) != '\n' && c != EOF)
{
stringPtr[i++] = (char) c;
if (i == strLength)
{
strLength *= strLength;
if ((stringPtr = realloc(stringPtr, strLength)) == NULL)
{
fprintf(stderr, "Unable to expand memory to hold char array. Exiting!\n");
return 2;
}
}
}
stringPtr[i] = '\0';
if (sizeof(stringPtr) < strLength)
{
stringPtr = realloc(stringPtr, i);
}
printf("\n\nString value: %s\n\n\n", stringPtr);
free(stringPtr);
stringPtr = NULL;
}
答案 0 :(得分:2)
我稍微修改了你的程序,以帮助弄清楚出了什么问题:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void)
{
unsigned int strLength = 32;
char *stringPtr = malloc(strLength);
if (!stringPtr)
{
fprintf(stderr, "failed to allocate %u bytes: %s\n",
strLength, strerror(errno));
return 1;
}
int c = EOF;
unsigned int i = 0;
while ((c = getchar()) != '\n' && c != EOF)
{
stringPtr[i++] = (char) c;
if (i == strLength)
{
unsigned int nStrLength = strLength;
nStrLength *= nStrLength;
if (nStrLength <= strLength)
{
fprintf(stderr, "cannot grow string of %u bytes any more\n",
strLength);
return 1;
}
if ((stringPtr = realloc(stringPtr, nStrLength)) == NULL)
{
fprintf(stderr,
"failed to enlarge string from %u to %u bytes: %s\n",
strLength, nStrLength, strerror(errno));
return 1;
}
strLength = nStrLength;
}
}
return 0;
}
当像你一样或多或少地运行时,这就是我得到的:
$ yes | tr -d '\n' | ./a.out
cannot grow string of 1048576 bytes any more
1048576是1兆字节,但更重要的是,它是2 20 。 2 20 的平方为2 40 ,大于2 32 -1,这是可以表示的最大值。 unsigned int
在此系统上。我预测您将在您的系统上获得相同的结果。
因此,我建议您进行三项更改:
unsigned int
变量都应该是size_t
。strLength
乘以2而不是单独使用。reallocarray
,这可能不在您的C库中,但您可以从链接中删除。reallocarray
仍然一般来说这是一个好主意,但它对这个类的数值溢出错误没有帮助,因为它是数组中溢出的项目数,而不是项目数和大小的乘积。的 强> 此外,这次不是您的直接问题,但为了将来参考,strerror(errno)
是您的朋友。当系统原语失败时,始终打印strerror(errno)
。