std :: vector резервный метод не может выделить достаточно памяти - PullRequest
2 голосов
/ 26 декабря 2009

В моем приложении C ++ есть класс буфера:

class Buffer
{
    public:
    Buffer(size_t res): _rpos(0), _wpos(0)
    {
        _storage.reserve(res);
    }

    protected:
    size_t _rpos, _wpos;
    std::vector<uint8> _storage;
}

Иногда использование конструктора завершается неудачно, потому что он не может выделить необходимое пространство памяти. Например, однажды вызов конструктора с res = 37 вызвал segfault со следующей трассировкой стека, которую я получил из дампа ядра:

#0  0x00007f916a176ed5 in raise () from /lib/libc.so.6
No symbol table info available.
#1  0x00007f916a1783f3 in abort () from /lib/libc.so.6
No symbol table info available.
#2  0x00007f916a1b33a8 in ?? () from /lib/libc.so.6
No symbol table info available.
#3  0x00007f916a1b8948 in ?? () from /lib/libc.so.6
No symbol table info available.
#4  0x00007f916a1bb17c in ?? () from /lib/libc.so.6
No symbol table info available.
#5  0x00007f916a1bca78 in malloc () from /lib/libc.so.6
No symbol table info available.
#6  0x00007f916ac0c16d in operator new (sz=37)
    at ../../.././libstdc++-v3/libsupc++/new_op.cc:52
        p = <value optimized out>
#7  0x00000000004e3d11 in std::vector<unsigned char, std::allocator<unsigned char> >::reserve (this=0x7f911bc49cc0, __n=31077)
    at /usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.4.2/../../../../include/c++/4.4.2/ext/new_allocator.h:89
        __old_size = 0
        __tmp = <value optimized out>

Я скомпилировал это приложение, используя GCC 4.4.2 в качестве 64-битного приложения, и использую его в Debian 5 x64.

Любая помощь очень ценится. Спасибо

Ответы [ 2 ]

8 голосов
/ 26 декабря 2009

Поскольку segfault находится в malloc, скорее всего какой-то другой код уничтожил кучу (т.е. записывается в части памяти, которые им не принадлежат и используются менеджером кучи).

Я рекомендую использовать Valgrind , чтобы найти, какой код уничтожает кучу.

2 голосов
/ 26 декабря 2009

Если вы не можете использовать Valgrind, чтобы выяснить, где ваша память повреждена из-за большой нагрузки, которую она вызывает, вы все равно можете протестировать с более легкими решениями.

Для серверного приложения, где Valgrind не был применим (поскольку платформа была на Solaris 8), у меня был довольно хороший результат с mpatrol (http://mpatrol.sf.net), но особенно с dmalloc (http://dmalloc.com).

В некоторой степени вы можете использовать их без перекомпиляции (просто перекомпоновка для dmalloc, предварительная загрузка библиотеки для mpatrol). Они заменят примитивы памяти для выполнения дополнительных проверок использования памяти (неверный аргумент для этих примитивов, чтение по одному, повреждение кучи, ...) Некоторые из этих проверок будут запущены именно тогда, когда проблема возникает, в то время как другие будет запущен немного позже, чем фактический плохой код. Настроив, какие проверки включены, и, когда применимо, частоту проверки, вы можете работать почти на полной скорости, выполняя основные проверки.

Я рекомендую перекомпилировать с dmalloc, чтобы получить так называемый 'FUNC_CHECK', для меня это добавило много точности в обнаружении ошибок с незначительными затратами на производительность.

...