LINUX.ORG.RU

C++, странная проблема с «new». Не даёт выделять мелкие куски.


0

2

Кросс-платформенное приложение «programname», которое работает под windows, но начало валиться с таким сообщением под linux:

programname: malloc.c:3097: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.

Эксперимент показал, что если убрать в одном месте ОДНОКРАТНЫЙ вызов «char *t = new char[1024]», то всё становится хорошо. Или если заменить «1024» на «1024*1024», то всё становится тоже хорошо.

Перед этим «new char[1024]» делается после нескольких сотен new + delete на небольшой объём памяти каждая (байт 60).

В чём может порыться собака? У меня слишком много мелких выделений и освобождений памяти? Несколько сотен мелких выделений и освобождений памяти оказывается достаточно, чтобы убить фрагментацией 3 гига свободной памяти?

★☆

Последнее исправление: kiverattes (всего исправлений: 2)

упрощенный вариант программы соорудить и выложить сможешь?
Заодно и версии gcc+glibc+ иных используемых библиотек.

Atlant ★★★★★
()
Ответ на: комментарий от Atlant

Ой, я боюсь не смогу, это куча кода... Эта куча кода вызывается из короткой main(). Главное не то, сколько багов в этой куче кода, а то, что если в конце этой коротенькой main написать new char[1024] или например new char[1];, всё валится вышеуказанным образом. Если вместо этого написать new char[1024*1024], то ничего не валится. Я конечно понимаю, что у меня возможны утечки памяти, но не на три гига - это я зуб даю.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

Главное не то, сколько багов в этой куче кода,

Хахаха. Именно это и главное. Ты портишь хип.

anonymous
()

проблема не в new, а в том что ты где-то в процессе этих new/delete раньше «разрушил» память. а при new твой баг вылез.

invy ★★★★★
()

В чём может порыться собака?

Где-то сделал buffer overflow и попортил служебную информацию аллокатора. man valgrind и править.

kemm
()

ммм... валгринд уже предлагали? ;)

aol ★★★★★
()
Ответ на: комментарий от kiverattes

Как можно «испортить хип» вызовами new + delete?

delete p;
delete p;

anonymous
()

Спасибо! Кажется дошло, что такое «портить хип»... Попробую познакомиться с valgrind.

kiverattes ★☆
() автор топика

char *t = new char[1024]

везде где можно используй:

vector<char> t[ 1024 ];
char t[ 1024 ];

вместе ручного выделения/освобождения памяти

anonymous
()

то var = «/>» не написать, то new не работает.. тред не читал

trashymichael ★★★
()

Открыл для себя Valgrind...

kiverattes ★☆
() автор топика
Ответ на: комментарий от yoghurt

Да и строка далеко не всегда массив одиночных байтов.

note173 ★★★★★
()
Ответ на: комментарий от stack_protector

Не, массив char-ов выделяется, чтобы гарантированно оперировать единицами байт, т.к. в стандарте C++ написано, что char гарантированно занимает 1 байт, остальные типы - ХЗ. Поэтому если надо быть уверенным в том, что я выделяю байты, а не блоки большего размера, я оперирую типом char. Конечно можно юзать malloc или ещё что-то, но если используется «new», то приходится использовать char.

kiverattes ★☆
() автор топика
Ответ на: комментарий от anonymous

vector<char> t[ 1024 ];

OMG да, так гораздо лучше :D

s0L
()
Ответ на: комментарий от stack_protector

Почему vector не уместен? Люди вот это наверное имеют ввиду:

std::vector<char> x;
x.reserve(1024);
x.resize(1024); // not needed?
char *px = &x.front();

kiverattes ★☆
() автор топика
Ответ на: комментарий от stack_protector

На выходе из области видимости и основана полезность этой конструкции. Вышла за область видимости - память удалилась, утечек нет, от забывчивости человека ничего не зависит.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

ну сравни сам...

auto_ptr<char> px(new char[1024]);
И если уж так хочется векторов, то
std::vector<char> x(1024);
std::vector<char> x(1024, 0); // так наверное юзабельнее

invy ★★★★★
()
Ответ на: комментарий от kiverattes

т.к. в стандарте C++ написано, что char гарантированно занимает 1 байт

ага, только не надо забывать, что этот байт может иметь размер 8, 16 или 32 бита

gaga
()
Ответ на: комментарий от kiverattes

ну тогда так и пиши, что твое «кросс-платформенное» приложение работает только на х86, а не ссылайся на стандарт.
Хинт: использование uint8_t вместо char повысит читаемость и (всякое бывает) переносимость
PS
почти все dsp имеют char > 8 бит
PPS
ну и на самом деле ты, конечно, по большому счету можешь не париться: ЕМНИП, posix требует CHAR_BITS == 8

gaga
()
Ответ на: комментарий от gaga

У понятия кросс-платформенный тоже есть ограничения. Например может оказаться, что 99% всех приложений, которые называются кросс-платфоренными откажутся работать на системах, когда байт будет равен 2 битам, например.

kiverattes ★☆
() автор топика
Ответ на: комментарий от kiverattes

когда байт будет равен 2 битам, например.

стандарты С и С++ гарантируют, что байт будет не меньше 8 бит

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.