#define HUGE_NUMBER ???
char string[HUGE_NUMBER];
do_something_with_the_string(string);
我想知道什么是我可以添加到char数组的最大数量,而不会冒任何潜在的内存问题,缓冲区溢出等风险。我想让用户输入,也许最大可能。
答案 0 :(得分:14)
请看Jack Klein的回复(见original post):
原始C标准(ANSI 1989 / ISO 1990)要求编译器 成功翻译至少一个 包含至少一个的程序 一组环境的例子 限制。其中一个限制是 能够创建至少一个对象 32,767字节。
这个最低限额是在 1999更新到C标准 至少65,535字节。
不需要C实现 提供大于此的对象 大小,这意味着他们不需要 允许一组更大的整数 than(int)(65535 / sizeof(int))。
在非常实际的方面,在现代 电脑,这是不可能的 事先预计阵列的大小 创建。它可以取决于像 物理内存量 安装在电脑上,金额 操作系统提供的虚拟内存, 其他任务的数量,司机, 和程序已经运行以及如何运行 正在使用的大量内存。所以你的 程序可能能够使用更多或 今天运行的内存少于它 可以使用昨天或它将能够 明天使用。
许多平台都是最严格的 对自动对象的限制,即 那些在函数内部定义的 没有使用'静态' 关键词。在某些平台上你可以 如果是,则创建更大的数组 静态或动态分配。
现在,为了提供稍微量身定制的答案,不要声明巨大的阵列以避免缓冲溢出。这与C中可以想到的最差实践接近。相反,花一些时间编写好的代码,并仔细确保不会发生缓冲区溢出。另外,如果您事先不知道阵列的大小,请查看malloc
,它可能会派上用场:P
答案 1 :(得分:7)
这取决于放置char string[HUGE_NUMBER];
的位置。
是否在函数内?然后,阵列将在堆栈上,如果和 你的操作系统增长速度有多快取决于操作系统。所以这里是一般规则:不要在堆栈上放置大型数组。
它是一个功能,然后它是全局的(进程内存),如果操作系统在尝试加载你的程序时无法分配那么多内存,你的程序将崩溃,你的程序将没有机会注意到(所以以下更好:)
大型数组应为malloc
。对于malloc,如果malloc
失败,操作系统将返回空指针,具体取决于操作系统及其分页方案和内存映射方案,这将在1)没有连续的空闲内存区域时失败足够大的数组或2)操作系统无法将足够的空闲物理内存区域映射到作为连续内存对您的进程显示的内存。
因此,对于大型数组,请执行以下操作:
char* largeArray = malloc(HUGE_NUMBER);
if(!largeArray) { do error recovery and display msg to user }
答案 2 :(得分:4)
声明任意大的数组以避免缓冲区溢出是不好的做法。如果您事先并不知道缓冲区需要多大,请使用malloc
或realloc
根据需要动态分配和扩展缓冲区,可能使用较小的固定大小的缓冲区作为中介。
示例:
#define PAGE_SIZE 1024 // 1K buffer; you can make this larger or smaller
/**
* Read up to the next newline character from the specified stream.
* Dynamically allocate and extend a buffer as necessary to hold
* the line contents.
*
* The final size of the generated buffer is written to bufferSize.
*
* Returns NULL if the buffer cannot be allocated or if extending it
* fails.
*/
char *getNextLine(FILE *stream, size_t *bufferSize)
{
char input[PAGE_SIZE]; // allocate
int done = 0;
char *targetBuffer = NULL;
*bufferSize = 0;
while (!done)
{
if(fgets(input, sizeof input, stream) != NULL)
{
char *tmp;
char *newline = strchr(input, '\n');
if (newline != NULL)
{
done = 1;
*newline = 0;
}
tmp = realloc(targetBuffer, sizeof *tmp * (*bufferSize + strlen(input)));
if (tmp)
{
targetBuffer = tmp;
*bufferSize += strlen(input);
strcat(targetBuffer, input);
}
else
{
free(targetBuffer);
targetBuffer = NULL;
*bufferSize = 0;
fprintf(stderr, "Unable to allocate or extend input buffer\n");
}
}
}
答案 3 :(得分:3)
如果要在堆栈上分配数组,那么您受到堆栈大小的限制(typically 1MB on Windows,其中一些将被使用,因此您甚至更少)。否则我想象限制会很大。
但是,使阵列非常大并不能解决缓冲区溢出问题。不要这样做。使用具有限制其缓冲区数量的机制的函数,以确保不会超出缓冲区,并使大小更合理(例如1K)。
答案 4 :(得分:1)
您可以使用malloc()
来获取比数组通常可以处理的更大的内存部分。
答案 5 :(得分:0)
好吧,缓冲区溢出不会因为HUGE_NUMBER的值太大而导致太小而不是写入的内容(写入索引HUGE_NUMBER或更高,并且你已经溢出缓冲区)。 / p>
除此之外,它将取决于机器。当然系统可以处理堆中的数百万,堆栈上有一百万左右(取决于其他压力),但肯定有一些系统无法处理超过几百个(小型嵌入式设备将是一个明显的例子)。虽然65,535是标准规定的最小值,但是一个非常小的设备可以指定该标准故意因此而离开。
实际上,在大型机器上,早在内存耗尽之前,就会以一种会影响性能的方式不必要地对内存施加压力。最好动态调整数组大小到合适的大小。