【问题标题】:How many chars can be in a char array?一个char数组可以有多少个字符?
【发布时间】:2011-07-18 03:19:55
【问题描述】:
#define HUGE_NUMBER ???

char string[HUGE_NUMBER];
do_something_with_the_string(string);

我想知道在不冒任何潜在内存问题、缓冲区溢出等风险的情况下,我可以添加到 char 数组的最大数量是多少。我想让用户输入它,并且可能是最大可能的。

【问题讨论】:

  • 这在很大程度上取决于您使用的 C 和您正在编译它的平台。

标签: c arrays memory char buffer


【解决方案1】:

声明任意大的数组以避免缓冲区溢出是不好的做法。如果您确实事先不知道缓冲区需要多大,请使用mallocrealloc 根据需要动态分配和扩展缓冲区,可能使用较小的固定大小的缓冲区作为中介。

例子:

#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");

       }
     }
   }

【讨论】:

    【解决方案2】:

    这取决于char string[HUGE_NUMBER]; 的放置位置。

    • 它在函数内部吗?然后数组将在堆栈上,if多快 您的操作系统可以增长堆栈取决于操作系统。所以这是一般规则:不要在堆栈上放置巨大的数组。

    • 它是否在函数之外,那么它是全局的(进程内存),如果操作系统在尝试加载您的程序时无法分配那么多内存,您的程序将崩溃并且您的程序将没有机会注意到那(所以以下更好:)

    • 大数组应该是malloc'ed。使用 malloc,如果 malloc 失败,操作系统将返回一个空指针,具体取决于操作系统及其分页方案和内存映射方案,这将在 1) 没有足够大的连续可用内存区域时失败对于数组或 2) 操作系统无法将足够的可用物理内存区域映射到在您的进程中显示为连续内存的内存。

    因此,对于大型数组,请执行以下操作:

    char* largeArray = malloc(HUGE_NUMBER);
    if(!largeArray) { do error recovery and display msg to user }
    

    【讨论】:

      【解决方案3】:

      如果要在堆栈上分配数组,那么您将受到堆栈大小的限制(typically 1MB on Windows,其中一些将被使用,因此您拥有的更少)。否则我想这个限制会很大。

      但是,使数组变得非常大并不能解决缓冲区溢出问题。不要这样做。使用具有限制它们使用的缓冲区数量机制的函数,以确保您不会超出缓冲区,并使大小更合理(例如 1K)。

      【讨论】:

        【解决方案4】:

        嗯,缓冲区溢出不会是由于 HUGE_NUMBER 的值太大而导致的,与写入它的值相比太小(写入索引 HUGE_NUMBER 或更高,并且您已经溢出了缓冲区)。

        除此之外,它还取决于机器。当然有一些系统可以处理堆中的数百万个,堆栈中的一百万个左右(取决于其他压力),但也有一些系统不能处理超过几百个(小型嵌入式设备将是一个明显的例子)。虽然 65,535 是标准指定的最小值,但一个非常小的设备可以指定为此故意偏离标准。

        实际上,在大型机器上,早在您实际耗尽内存之前,您就会以一种会影响性能的方式不必要地对内存施加压力。最好将数组动态调整为适当的大小。

        【讨论】:

          【解决方案5】:

          查看 Jack Klein 的回复(请参阅 original post):

          最初的 C 标准(ANSI 1989/ISO 1990) 要求编译器 成功翻译至少一个 程序至少包含一个 一组环境示例 限制。其中一个限制是 至少能够创建一个对象 32,767 字节。

          这个最低限制是在 1999 年更新到 C 标准 至少 65,535 字节。

          不需要 C 实现 提供比这更大的对象 大小,这意味着他们不需要 允许更大的整数数组 比 (int)(65535 / sizeof(int))。

          在非常实用的术语中,在现代 电脑,不能说 提前一个数组可以有多大 创建的。它可以取决于诸如 物理内存量 安装在电脑上,金额 操作系统提供的虚拟内存, 其他任务、驱动程序的数量, 和已经运行的程序以及如何运行 正在使用的大量内存。所以你的 程序可能能够使用更多或 今天运行的内存比它少 昨天可以用,或者可以 明天用。

          许多平台都设置了最严格的 对自动对象的限制,即 那些在函数内部定义的 不使用“静态” 关键词。在某些平台上,您可以 如果它们是,则创建更大的数组 静态或动态分配。

          现在,为了提供一个更加量身定制的答案,不要声明巨大的数组以避免缓冲区溢出。这接近人们在 C 中所能想到的最糟糕的做法。相反,花一些时间编写好的代码,并仔细确保不会发生缓冲区溢出。另外,如果您事先不知道数组的大小,请查看malloc,它可能会派上用场:P

          【讨论】:

            【解决方案6】:

            您可以使用malloc() 获得比通常数组可以处理的更大的内存部分。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-11-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多