在 C 中初始化一个 16mb 的数组

Initialize a 16mb array in C

我对 'C' 比较陌生,希望对这个主题有一些见解。

基本上,我正在尝试创建一个 16 MB 的数组并检查内存内容是否初始化为零或“\0”或学校项目的一些垃圾值。

像这样:

char buffer[16*1024*1024];

我知道程序堆栈的大小是有限制的,显然我遇到了分段错误。可以使用 malloc() 以某种方式完成吗?

当然可以:

int memSize = 16*1024*1024;
char* buffer = malloc( memSize );
if ( buffer != 0 )
{
    // check contents
    for ( i = 0; i < memSize; i++ )
    {
        if ( buffer[i] != 0 )
        {
            // holler
            break;
        }
    }


    free( buffer );
}

您可以像这样使用 malloc 初始化内存:

#define MEM_SIZE_16MB   ( 16 * 1024 * 1024 )

char *buffer = malloc(MEM_SIZE_16MB * sizeof(char) );
if (buffer == NULL ) {
    // unable to allocate memory. stop here or undefined behavior happens
}

然后您可以检查内存中的值(请注意,这将打印很长时间):

for (int i = 0; i < MEM_SIZE_16MB; i++) {
    if( i%16 == 0 ) {
        // print a newline and the memory address every 16 bytes so 
        // it's a little easier to read
        printf("\nAddr: %08p: ", &buffer[i]); 
    }
    printf("%02x ", buffer[i]);
}
printf("\n");  // one final newline

完成后不要忘记释放内存

free(buffer);

是的,您可能需要使用 malloc() 执行此操作,原因如下:

当任何程序 (process ... thread ...) 启动时,它会获得一块内存,用于存储 (其中其他事情...) "local" 变量。这个区域叫做"the stack."它肯定不够大,无法存储 16 兆字节。

但是还有 另一个 内存区域可供任何程序使用:它的“”。这个区域(顾名思义,"heap,"意在暗示...)没有内在的结构:它只是一个存储池,通常足够大,可以存储很多兆字节。您只需 malloc() 您需要的字节数,然后 free() 那些字节。

简单定义一个type对应你需要存储的结构,然后malloc(sizeof(type))。存储将来自堆。 (基本上,堆就是 for ...)

顺便说一下,有一个名为 calloc() 的库函数会保留一个区域 "known zero." 此外,它可能会使用巧妙的操作系统技巧来非常有效地做到这一点。

严格来说,代码无法在不冒未定义行为风险的情况下检查 buffer 是否未归零。如果类型是 unsigned char,那么没问题。但是char,可能有符号,可能有陷阱值。尝试使用该值会导致 UB。

char buffer[16*1024*1024];
// Potential UB
if (buffer[0])  ...

最好使用不能有陷阱值的 unsigned char

#define N (16LU*1204*1204)
unsigned char *buffer = malloc(N);
if (buffer) {
   for (size_t i = 0; i<N; i++) {
     if (buffer[i]) Note_NonZeroValue();
   }
}

// Clean-up when done.
free(buffer);
buffer = 0;

C 的棘手之处在于,即使 char 没有陷阱值,一些聪明的编译器也可以识别代码正在尝试执行符合规范的 UB 然后将 if (buffer[0]) 优化为 nothing。禁止读取未初始化的非 unsigned char 数据。