代码之家  ›  专栏  ›  技术社区  ›  adk

数组索引限制(C)

  •  3
  • adk  · 技术社区  · 15 年前

    在带有16GB RAM的Linux上,为什么会出现以下错误:

    #include <stdlib.h>
    
    #define N 44000
    
    int main(void) {
        long width = N*2 - 1;
        int * c = (int *) calloc(width*N, sizeof(int));
        c[N/2] = 1;
        return 0;
    }
    

    根据gdb,问题来自c[n/2]=1,但原因是什么?

    7 回复  |  直到 13 年前
        1
  •  4
  •   Peter Mortensen icecrime    13 年前

    您分配了大约14-15GB的内存,无论什么原因,分配器都不能 现在给你这么多-因此 calloc 返回空值,并在取消对空指针的引用时执行SegFault。

    检查calloc是否返回空值。

    假设您正在64位Linux下编译64位程序。如果您正在执行其他操作-您可能会将计算溢出到 分配 如果系统中的long不是64位。

    例如,尝试

    #include    <stdlib.h>
    #include    <stdio.h>
    
    #define N    44000L
    
    int main(void)
    {
        size_t width = N * 2 - 1;
        printf("Longs are %lu bytes. About to allocate %lu bytes\n",
               sizeof(long), width * N * sizeof(int));
        int *c = calloc(width * N, sizeof(int));
        if (c == NULL) {
            perror("calloc");
            return 1;
        }
        c[N / 2] = 1;
        return 0;
    }
    
        2
  •  6
  •   JaredPar    15 年前

    可能是因为calloc的返回值为空。

    框中物理RAM的数量与您可以使用calloc/malloc/realloc分配的内存量没有直接关系。这更直接地由进程可用的剩余虚拟内存量决定。

        3
  •  6
  •   bbum    13 年前

    您的计算溢出了32位有符号整数的范围,“long”可能就是这个范围。你应该用尺寸而不是长的。这可以保证能够容纳系统可以分配的最大内存块的大小。

        4
  •  2
  •   Peter Mortensen icecrime    13 年前

    您要求的是2.6GB的RAM(不,您不是--您要求的是64位上的14GB…2.6GB溢出的32位截止计算)。显然,Linux的堆被充分利用 calloc() 不能一次分配那么多。

    这在MacOSX(32位和64位)上都可以正常工作,但几乎不工作(而且很可能会在不同系统上发生故障 dyld 共享缓存和框架)。

    当然,在任何系统中,它都应该在64位下运行(即使计算错误的32位版本也能运行,但只是巧合)。

    还有一个细节:在“真实世界应用程序”中,随着应用程序的复杂性和/或运行时间的增加,最大的连续分配将大大减少。使用的堆越多,分配的连续空间就越少。

        5
  •  2
  •   Peter Mortensen icecrime    13 年前

    您可能希望将定义更改为:

    #define N    44000L
    

    只是为了确保数学是在长分辨率下完成的。您可能正在为 calloc .

    Calloc 可能失败并返回空值,这将导致问题。

        6
  •  1
  •   John Bode    15 年前

    从美元到甜甜圈 calloc() 返回了空值,因为它不能满足请求,因此尝试遵从C导致了segfault。你应该 总是 检查的结果 *alloc() 以确保它不为空。

        7
  •  1
  •   Peter Mortensen icecrime    13 年前

    创建一个14GB文件,内存映射它。