内存或资源分配失败需分路径排查:内核级查dmesg(OOM/SLAB/页分配失败),用户态查/var/log/messages或journalctl,进程级看/proc/pid/status和maps,还需排除ulimit/cgroup限制及静默malloc失败。

内存或资源分配失败的日志不会统一出现在某一个固定位置,得根据失败类型分路径查——malloc 失败通常不打日志,但 fork、exec、内核级分配(如 kmalloc)失败会留下痕迹,关键看谁在报错。
查 dmesg 里内核 OOM 和分配拒绝记录
内核在无法满足内存分配请求时,会直接写入环形缓冲区,dmesg 是第一手来源。OOM killer 触发、SLAB 分配失败、页分配失败都会在这里出现。
-
dmesg | grep -i "out of memory\|oom\|failed to allocate\|cannot allocate memory"—— 最常用组合,覆盖大部分内核级分配失败 - 注意时间戳:OOM 事件常发生在进程被杀前几秒,
dmesg -T可带本地时间查看时序 - 如果系统启用了
vm.panic_on_oom=1,分配失败会直接 panic,dmesg结尾会有Kernel panic行
查 /var/log/messages 或 /var/log/syslog 中用户态服务的 malloc 失败回溯
应用层调用 malloc 返回 NULL 本身不记日志,但多数服务会在检测到后打印错误,比如 Nginx 启动时报 shm_open() failed、PostgreSQL 报 out of shared memory,这些会落到系统日志。
grep -n "Cannot allocate memory\|Out of memory\|failed to allocate" /var/log/messages- 某些服务(如 systemd-journald)会把 stderr 输出自动捕获进
journalctl,所以别只盯文件日志 - 若服务用
systemd管理,优先跑journalctl -u,比翻--since "1 hour ago" /var/log/messages更准
查具体进程的 /proc//status 和 maps 辅助判断是否真因分配失败退出
很多“分配失败”其实是进程收到 SIGKILL(OOM killer 杀的)或 SIGSEGV(访问了未分配内存),不能光看错误字符串。
- 先用
ps aux | grep找 PID,再看cat /proc/——/status | grep -E "VmSize|VmRSS|SigQ|State" State: Z表示僵死,VmRSS突增可能预示 OOM 前兆 -
cat /proc/查堆地址范围,结合/maps | awk '$6 ~ /\[heap\]$/ {print $1}' strace -p可确认最后一次分配调用是否返回 -1-e trace=brk,mmap,mremap - 如果进程已退出,
journalctl _PID=有时还能捞出它死前最后几条日志(systemd 保留短时缓存)
警惕 ulimit 和 cgroup 限制导致的“假分配失败”
不是所有“无法分配”都源于物理内存不足;ulimit -v(虚拟内存)、ulimit -d(数据段)、cgroup 的 memory.limit_in_bytes 都会拦截分配请求,并静默失败或返回 ENOMEM。
- 查当前 shell 限制:
ulimit -a,重点看virtual memory (kbytes)和max memory size (kbytes) - 查 cgroup 限制:
cat /sys/fs/cgroup/memory/(路径取决于 systemd scope 或手动挂载)/memory.limit_in_bytes - 这类限制触发的失败,
dmesg不会记录,strace却能看到mmap直接返回-1 ENOMEM
真正难定位的是那些没触发内核日志、又没被服务主动记录的 malloc 失败——这时候得靠 strace 实时抓,或者加 LD_PRELOAD hook malloc,否则日志里根本不会出现“分配失败”四个字。











