You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

访问大型数组时程序被“Killed”的原因及安全数组大小判定

C++程序出现“Killed”提示的原因及解决方案

问题描述

运行以下C++程序时,当N设为50亿时,程序在写入数组阶段崩溃,控制台打印“Killed”并以状态码137退出;设为500亿时会触发std::bad_alloc;设为10亿时程序运行正常:

#include <stddef.h>

int main() {
    constexpr size_t N{5'000'000'000};
    unsigned int *bigdata;
    bigdata = new unsigned int[N];
    for (size_t i=0; i<N; i++) 
        bigdata[i] = i;
    return 0;
}

补充:尝试使用获取系统总内存的代码分配内存,依然触发“Killed”:

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

unsigned long long getTotalSystemMemory() {
  long pages = sysconf(_SC_PHYS_PAGES);
  long page_size = sysconf(_SC_PAGE_SIZE);
  return pages * page_size;
}

int main() {
  size_t N = getTotalSystemMemory();
  printf("Size: %zu \n", N);

  unsigned int *bigdata = (unsigned int *)malloc(N);
  for (size_t i = 0; i < N / sizeof(unsigned int) - 1; i++)
    bigdata[i] = i;
  return 0;
}

程序输出:

Size: 16'439'369'728       // 手动添加分隔符
Killed

原因分析

  1. 状态码137的含义:进程被系统的**OOM Killer(内存不足杀手)**终止。当系统物理内存+交换区耗尽时,OOM Killer会选择占用内存最多的进程强制终止,释放内存避免系统崩溃。
  2. 惰性内存分配机制:Linux下malloc/new默认是惰性分配——调用时仅分配虚拟内存空间,实际物理内存只有在向内存地址写入数据时才会被真正分配。
    • 当N=500亿时,需要的虚拟内存(500亿×4字节=200GB)超过了进程地址空间上限,因此直接触发std::bad_alloc。
    • 当N=50亿时,虚拟内存(20GB)可以分配,但写入时系统物理内存+交换区不足以提供20GB实际内存,OOM Killer启动杀掉进程。
    • 当N=10亿时,实际需要的4GB内存在系统可用范围内,所以正常运行。
  3. 总内存≠可用内存:补充代码中获取的是系统总物理内存,但系统本身已占用部分内存,剩余可用内存远小于总内存,写入时内存不足触发OOM Killer。

如何确定安全的数组大小

1. 查看系统可用内存

在Linux终端执行free -h命令,关注available字段,这是系统实际可以分配给进程的内存(包含缓存、缓冲区可释放部分)。

2. 在代码中获取可用内存(Linux)

读取/proc/meminfo文件中的MemAvailable值,这比总内存更准确:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>

size_t getAvailableMemory() {
    std::ifstream meminfo("/proc/meminfo");
    std::string line;
    size_t memAvailable = 0;
    while (std::getline(meminfo, line)) {
        if (line.compare(0, 13, "MemAvailable:") == 0) {
            memAvailable = std::stoull(line.substr(14)) * 1024; // 转换为字节
            break;
        }
    }
    return memAvailable;
}

3. 安全分配内存的原则

  • 预留足够余量:不要把可用内存全部分配,建议预留1GB以上的内存给系统和其他进程,避免内存波动触发OOM Killer。
  • 捕获分配异常:始终捕获std::bad_alloc异常,处理虚拟内存不足的情况。
  • 跨平台适配:Windows系统可使用GlobalMemoryStatusEx API获取可用内存,macOS可使用sysctl相关接口。

安全分配示例代码

#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>

size_t getAvailableMemory() {
    std::ifstream meminfo("/proc/meminfo");
    std::string line;
    size_t memAvailable = 0;
    while (std::getline(meminfo, line)) {
        if (line.compare(0, 13, "MemAvailable:") == 0) {
            memAvailable = std::stoull(line.substr(14)) * 1024;
            break;
        }
    }
    return memAvailable;
}

int main() {
    size_t available = getAvailableMemory();
    if (available == 0) {
        std::cerr << "Failed to get available memory\n";
        return 1;
    }
    std::cout << "Available memory: " << available << " bytes\n";

    // 预留1GB内存余量
    const size_t RESERVE = 1024 * 1024 * 1024;
    if (available <= RESERVE) {
        std::cerr << "Insufficient available memory\n";
        return 1;
    }
    size_t safeElementCount = (available - RESERVE) / sizeof(unsigned int);

    try {
        unsigned int* bigdata = new unsigned int[safeElementCount];
        for (size_t i = 0; i < safeElementCount; ++i) {
            bigdata[i] = static_cast<unsigned int>(i);
        }
        std::cout << "Successfully allocated array with " << safeElementCount << " elements\n";
        delete[] bigdata;
    } catch (const std::bad_alloc& e) {
        std::cerr << "Allocation failed: " << e.what() << "\n";
        return 1;
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者user23952

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 13:10:54