C/C++中,局部变量(如数组)通常分配在栈(stack)上,而栈的大小是有限的。声明一个超出栈容量的大数组会导致栈溢出(Stack Overflow)。栈的默认大小通常在几百KB到几MB之间,具体取决于操作系统和编译器的设置。

1、使用堆分配

改用 malloccalloc 在堆上分配大数组,堆的大小比栈更大。

#include <stdlib.h>
#include <stdio.h>

void largeArrayExample() {
    int *arr = (int *)malloc(10000000 * sizeof(int)); // 在堆上分配
    if (arr == NULL) {
        printf("内存分配失败!\n");
        return;
    }
    // 使用数组
    arr[0] = 42;
    printf("arr[0] = %d\n", arr[0]);

    free(arr); // 释放内存
}

int main() {
    largeArrayExample();
    return 0;
}

2、使用静态或全局变量

静态变量和全局变量存储在数据段(data segment)中,而不是栈,因此它们不会受栈大小限制。

#include <stdio.h>

static int arr[10000000]; // 静态变量

void largeArrayExample() {
    arr[0] = 42;
    printf("arr[0] = %d\n", arr[0]);
}

int main() {
    largeArrayExample();
    return 0;
}

3、增加栈大小

在某些情况下,可以通过修改编译器或操作系统设置来增加栈大小。

1)Linux

使用 ulimit 增加栈大小。

ulimit -s unlimited

2)Windows (Visual Studio)

在项目属性中调整栈大小。

右键点击项目 -> 属性。

转到 链接器 -> 系统 -> 堆栈大小。

修改默认栈大小。

4、使用分块数组

如果大数组可以分割成更小的块,则使用多个小块数组代替单个大数组。分块数组是一种用于管理大数组或动态数据的技术,可以有效地减少内存分配的开销,同时方便对数组数据进行分块管理。分块数组通常用于实现高效的数据操作,特别是在数据量非常大或者需要频繁调整大小的场景。

#include <stdio.h>
#include <stdlib.h>

#define BLOCK_SIZE 100  // 每块的大小
#define TOTAL_ELEMENTS 10000  // 总的元素数量
#define BLOCK_COUNT (TOTAL_ELEMENTS / BLOCK_SIZE)  // 块的数量

int main() {
    // 创建一个指针数组,用于存储每块的地址
    int *blocks[BLOCK_COUNT];

    // 为每块分配内存
    for (int i = 0; i < BLOCK_COUNT; i++) {
        blocks[i] = (int *)malloc(BLOCK_SIZE * sizeof(int));
        if (blocks[i] == NULL) {
            printf("Memory allocation failed for block %d\n", i);
            // 释放已分配的内存,避免内存泄漏
            for (int j = 0; j < i; j++) {
                free(blocks[j]);
            }
            return 1;
        }
    }

    // 填充数据
    for (int i = 0; i < TOTAL_ELEMENTS; i++) {
        int block_index = i / BLOCK_SIZE;  // 第几块
        int offset = i % BLOCK_SIZE;      // 块内偏移
        blocks[block_index][offset] = i; // 存储数据
    }

    // 读取和打印数据
    for (int i = 0; i < TOTAL_ELEMENTS; i++) {
        int block_index = i / BLOCK_SIZE;  // 第几块
        int offset = i % BLOCK_SIZE;      // 块内偏移
        printf("%d ", blocks[block_index][offset]);
        if (i % 1000 == 999) {  // 每 1000 个元素换行
            printf("\n");
        }
    }

    // 释放内存
    for (int i = 0; i < BLOCK_COUNT; i++) {
        free(blocks[i]);
    }

    return 0;
}