我的程序被“杀死”了。

7

根据这个问题中的建议,可能是由内核导致。我想知道为什么我被杀死了,比如暗杀发生的函数。

此外,有没有办法让我的程序正常执行?


编年史

我的程序可以正常执行。然而,我们遇到了一个大型数据集,1,000,000 x 960个浮点数,我家里的笔记本电脑无法处理(会出现std::bad_alloc())。

现在,我在实验室里,使用一个拥有9.8 GiB内存和3.00GHz × 4处理器的台式机,其内存是家用笔记本的两倍以上。

在家中,数据集无法加载到std::vector中,数据存储在其中。在这里,实验室里成功地完成了这个任务,并继续构建数据结构。

那是我最后一次听到有关它的消息:

Start building...
Killed

实验室的桌面电脑运行Debian 8操作系统。我的程序在数据集的子集中(特别是1.00.000 x 960浮点数)表现正常。


编辑

strace输出现已可用:

...
brk..
brk(0x352435000)                        = 0x352414000
mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7f09c1563000
munmap(0x7f09c1563000, 44683264)        = 0
munmap(0x7f09c8000000, 22425600)        = 0
mprotect(0x7f09c4000000, 135168, PROT_READ|PROT_WRITE) = 0
...
mprotect(0x7f09c6360000, 8003584, PROT_READ|PROT_WRITE) = 0
+++ killed by SIGKILL +++

这告诉我们我没有内存了,我猜测


1
也许你正在分配过多的内存。 - Basile Starynkevitch
看了你的问题后,我真的忍不住笑了 :D - Arnab Nandy
2
使用g++ -Wall -Wextra -g编译您的程序,然后使用调试器gdbvalgrindstrace; 但是您的程序有错误。同时在网上搜索 linux memory overcommit. - Basile Starynkevitch
1
程序被杀死而不是优雅地失败的原因是过度承诺。为了在程序中获得干净的内存分配失败,禁用过度承诺(这不会使您的程序工作,只能帮助您理解正在发生的事情)。至于为什么过度承诺会阻止有用的诊断,现在您知道“功能”的名称后,就不应该有困难找到这些信息了。 - Pascal Cuoq
你的机器上配置了交换空间吗?只有在所有RAM和交换空间都用尽之后,OOM killer才会开始杀死程序。考虑到可能有一些程序(或其部分)只需要常驻内存,而不需要主动运行,那么它们可以通过虚拟内存管理器(VMM)进行页面调入和调出。 - Lie Ryan
显示剩余9条评论
2个回答

5
在C++中,float是一个单精度(32位)浮点数:http://en.wikipedia.org/wiki/Single-precision_floating-point_format。这意味着您正在分配(不包括开销)3,840,000,000字节的数据。
或者大约是3.57627869千兆字节。
让我们安全地假设向量的头部与数据相比微不足道,并继续使用此数字。
这是一个巨大的数据量,Linux可能会认为这只是一个内存泄漏,并通过杀死应用程序来保护自己:https://unix.stackexchange.com/questions/136291/will-linux-start-killing-my-processes-without-asking-me-if-memory-gets-short
我认为这不是一个过度提交的问题,因为您实际上在一个单一应用程序中使用了近一半的内存。
但是也许..只是为了好玩..你正在构建一个32位应用程序吗?
如果是32位构建,则您正在接近程序可以寻址的2 ^ 32(4GB)内存空间。
因此,如果您有另一个大向量分配..嘣嘣嘣。

1
bum³ 让我感到害怕。字节数是正确的。我家里的笔记本电脑运行在 32 位上。你认为这有什么联系吗?给你一个赞,回答得真好。 - gsamaras
我不确定,但这是我的第一个怀疑。首先考虑在较小的数据集上测试您的程序(例如一半大小),如果它可以运行,那么我敢打赌应用程序无法分配必要的内存,并被内核阻止包装其内存空间。 - Henrik
我不确定你是否回答了我的32位问题。请查看我的编辑以获取更小的数据集。 - gsamaras
1
除非你在向其中添加元素时提前保留正确数量的空间,否则std::vector每次需要增长时都会将其内存占用量翻倍。例如,从16个元素到32个元素再到64个元素等等,所以它可能会增长到超出你实际需要的大小。尝试使用'reserve'来精确得到vector需要的元素数量。 - LawfulEvil
我现在非常确定你无法分配所需的内存,可能的解释是你试图在32位应用程序中分配超过允许的内存。关于解决方案,LawfulEvil很懂行,- 你是否在分配之前为数据保留了空间?否则那就是你的解决方案!- 否则考虑一下,是否绝对必要一次性将整个数据集保存在内存中,或者如果可能的话加载一个子集,进行计算,卸载,加载下一个子集,依此类推... - Henrik
@LawfulEvil 在这里使用 reserve() 不是一个好选择,更好的建议是使用 resize() 来获取你需要的内存大小。我认为 reserve() 可能会浪费一些空间。我在实验室电脑上编译了代码,那是64位的 Henrik。我会检查建议是什么。 - gsamaras

0

首先安装信号处理程序,例如:

static bool installSignalHandler(int sigNumber, void (*handler)(int) = signal_handler)
{
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_flags = SA_SIGINFO;
    action.sa_sigaction = signal_handler_action;
    return !sigaction(sigNumber, &action, NULL);
}

调用它:

installSignalHandler(SIGINT);
installSignalHandler(SIGTERM);

接下来将执行以下代码:

static void signal_handler_action(int sig, siginfo_t *siginfo, void* content) 
{
    switch(sig) {
        case SIGHUP:
            break;
        case SIGUSR1:
            break;
        case SIGTERM:
            break;
        case SIGINT:
            break;
        case SIGPIPE:
            return;
    }
}

查看 siginfo_t 结构以获取所需的数据

printf("Continue. Signo: %d - code: %d - value: %d - errno: %d - pid: %ld - uid: %ld - addr %p - status %d - band %d",
                      siginfo->si_signo, siginfo->si_code, siginfo->si_value, siginfo->si_errno, siginfo->si_pid, siginfo->si_uid, siginfo->si_addr,
                      siginfo->si_status, siginfo->si_band);

不,那是错误的方法。顺便说一句,signal(7) 禁止在信号处理程序中调用 printf - Basile Starynkevitch
我添加了printf,因为我不能把我用的代码放到生产环境中,使用syslog。 - Jose Palma
1
既然 printfsyslog 都不是异步信号安全函数,因此在信号处理程序中使用它们都被禁止。 - Basile Starynkevitch
我担心@BasileStarynkevitch是正确的,从我们在大学里所做的来看。 - gsamaras
这些函数并非被禁止,但不建议使用,因为它们可能会抛出新的信号,导致代码挂起或以未定义的方式运行。有时我们需要使用正确的词语 :-)。无论如何,您可能已经耗尽了内存,内核正在使用 sigkill/sigterm 杀死您的程序。您可以检查 dmesg 或使用 strace 运行程序。 - Jose Palma
@Raistmaj 我现在将运行 strace。 :) - gsamaras

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接