std :: bad_alloc исключение, хотя свободной памяти достаточно

мой код работает под 64-битным Linux (openSUSE 13.1 x86_64), компилятор - gcc (SUSE Linux) 4.8.1. В какой-то момент выполнения моей программы я получаю исключение std :: bad_alloc, которое возникает из-за вызова std :: vector push_back. Как видно в gdb:

(gdb) bt
#0  0x00007ffff6053849 in raise () from /lib64/libc.so.6
#1  0x00007ffff6054cd8 in abort () from /lib64/libc.so.6
#2  0x00007ffff694c655 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6
#3  0x00007ffff694a7c6 in ?? () from /usr/lib64/libstdc++.so.6
#4  0x00007ffff694a7f3 in std::terminate() () from /usr/lib64/libstdc++.so.6
#5  0x00007ffff694aa1e in __cxa_throw () from /usr/lib64/libstdc++.so.6
#6  0x00007ffff694af1d in operator new(unsigned long) () from /usr/lib64/libstdc++.so.6
#7  0x0000000000457ca6 in allocate (__n=8388608, this=0x7ffffffe1f80)
    at /usr/include/c++/4.8/ext/new_allocator.h:104
#8  _M_allocate (__n=8388608, this=0x7ffffffe1f80) at /usr/include/c++/4.8/bits/stl_vector.h:168
#9  std::vector<std::pair<long, long>, std::allocator<std::pair<long, long> > >::_M_insert_aux (
    this=this@entry=0x7ffffffe1f80, __position=..., __x=...) at /usr/include/c++/4.8/bits/vector.tcc:345
#10 0x000000000045335c in push_back (__x=..., this=0x7ffffffe1f80) at /usr/include/c++/4.8/bits/stl_vector.h:913
#11 c_RoutingNetzwerk::LoescheAktuelleKnoten (this=this@entry=0x7ffffffe2f30,
    aktuelle_knoten=std::vector of length 12803276, capacity 16777216 = {...}, ebene=ebene@entry=0,
    aktueller_kantengrad=std::vector of length 17266677, capacity 17266677 = {...}, algo=...,
    neue_abgehende_kanten=std::vector of length 4194304, capacity 4194304 = {...},
    neue_eingehende_kanten=std::vector of length 4194304, capacity 4194304 = {...})
    at RoutingAlgorithmus/RoutingNetzwerk.cpp:3275

Вызов neue_abgehende_kanten.push_back (...) удваивает размер вектора, поэтому я пытаюсь выделить 4194304 * 2 * 16 байтов = 128 МБ, и это не удается.

С другой стороны, у меня более чем достаточно памяти (всего 132 ГБ), и достаточно свободной памяти (снимок сделан, когда моя программа прерывается в отладчике):

m2883:~ # free -m
             total       used       free     shared    buffers     cached
Mem:        129151     128582        568          0         59      56334
-/+ buffers/cache:      72189      56962
Swap:         8195          5       8190

Есть идеи, почему распределение все же не выполняется? Мне кажется, что система не освобождает свои кеши для использования моей программой ?!


Я просто попробовал провести небольшой эксперимент и придумал

#include <cstdlib>
#include <stdio.h>

int main( int argc, char** argv)
{
    void* p = calloc( 1, 256 * 1024 * 1024 );
    if ( !p )
        printf( "failed\n" );
    else
        printf( "all done\n" );
}

Это все еще работает для 128 МБ, но не работает для 256 МБ.

И:

m2883:~ # free -mh
             total       used       free     shared    buffers     cached
Mem:          126G       125G       593M         0B        60M        54G
-/+ buffers/cache:        70G        55G
Swap:         8.0G       5.4M       8.0G

transit@m2883:~/test> ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 1033140
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1033140
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Кажется, что сервер каким-то образом неправильно настроен. Даже в недавно загруженной системе, в которой ничего не работает, кроме нескольких системных служб, я не могу выделить более 70 ГБ, которые я прочитал как 64 ГБ + 8 ГБ пространства подкачки. Я связался с хостером сервера и пожаловался на ситуацию.


person Heiko Petzsch    schedule 31.03.2015    source источник
comment
Возможно, в вашей системе есть ограничение на доступную память для каждого процесса?   -  person CiaPan    schedule 31.03.2015
comment
Не могли бы вы использовать вместо этого free -mh? Единицы неясны. Ваша куча могла быть повреждена.   -  person chmike    schedule 31.03.2015
comment
Дело не только в количестве свободной памяти. Это необходимый объем непрерывной памяти.   -  person PaulMcKenzie    schedule 31.03.2015
comment
Тестовая программа у меня работает нормально, система 16 ГБ с Ubuntu 14.10. Посмотрите на конфигурацию вашей системы, а не на C ++.   -  person dascandy    schedule 31.03.2015
comment
Я должен добавить, что есть две другие программы, работающие одновременно, которые потребляют почти 70 ГБ. Я не сомневаюсь, что их убийство позволит мне выделить 256M   -  person Heiko Petzsch    schedule 31.03.2015
comment
Есть те же проблемы, любое решение, что было не так?   -  person Dominic Jonas    schedule 22.09.2016


Ответы (1)


Трудно сказать наверняка, не имея информации о вашем коде и конфигурации системы.

Симптом можно объяснить фрагментацией памяти. Память, используемая вектором, является непрерывной, и даже если общий объем доступной памяти достаточен, выделение не удастся, если нет единого непрерывного блока требуемого размера, доступного для выделения.

Повторное выделение, освобождение и перераспределение может легко привести к фрагментации памяти.

Превышение некоторой квоты также объясняет такое поведение.

person Peter    schedule 31.03.2015
comment
Память, используемая кешами, не может быть фрагментирована, не так ли ?! - person Heiko Petzsch; 31.03.2015
comment
Любая память может стать фрагментированной. Фрагментация - это результат использования (например, шаблоны распределения и освобождения). - person Peter; 31.03.2015