LINUX.ORG.RU

std::vector валится на push_back/emplace_back с сегфолтом О_О

 ,


1

5

Сабж.

Валится при size()==16.

Валится редко, но достаточно одного раза.

Переписал сначала добавление элементов в std::list, затем для вектора resize и копирование из списка - все работает.

Но вообще то это странный косяк... кто нить сталкивался?

★★★★★

Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от AIv

-Wall ес-но включено и молчит.

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

возможно, но это связанено с рядом проблем, можно я не буду их озвучивать?

Да не проблема. Просто смена компилятора помогает искать ошибки, связанные с порчей памяти.

Про valgrind я уже писал - при его производительности я не дождусь результатов отладки.

Так ведь можно выбрать минимальную нагрузку, на которой наблюдаются крахи и запустить эту версию в фоне или на ночь/выходные.

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

Что там уметь...

gdb программа core
(gdb) bt
....
(gdb) frame номеркадра
(gdb) print имяпеременной

Дел на 2 минуты, если внутренности вектора повреждены - будет заметно, если нет - ты потратил всего 2 минуты.

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

Был бы W vector-ом, то у swap-а бы вообще никакого оверхеда не было бы.

Был бы скорей всего. push/emplace не добавляют по одному элементу, там идет типа удвоение при нехватке места. При swap эта лишняя память приходила бы в dstW.

Скажите, а plasts — это член SpaceModel?

Да, это вектор пойнтеров на довольно сложные полиморфные объекты, но они за пять лет очень хорошо отлажены.

Может ли быть так, что работа с методами SpaceModel идет из разных потоков? Т.е. в одном потоке работает mk_well, а во втором кто-то модифицирует plasts?

Нет. И работа идет в одном потоке, и plasts будучи единожды созданными больше никогда не модифицируются.

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

Э... че то я не вижу куда оно отложило core. И там все это стартует из под питона, gdb емнип его не ел.

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

И там все это стартует из под питона, gdb емнип его не ел.

Емнип, gdb /usr/bin/python core

А коры может не быть, если она в лимит не уместилась, тогда ulimit -c unlimited

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Таак, завелось... корка 3.6Гб.

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `python linev.py --zoom 0.5 0.5 0.5 10000'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f1b8e28112f in _int_free (av=0x7f1b8e5c0760 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3996
3996    malloc.c: No such file or directory.
(gdb) bt
#0  0x00007f1b8e28112f in _int_free (av=0x7f1b8e5c0760 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3996
#1  0x00007f1b8813916a in deallocate (this=0x7ffd34551290, __p=<optimized out>) at /usr/include/c++/4.8/ext/new_allocator.h:110
#2  _M_deallocate (this=0x7ffd34551290, __n=<optimized out>, __p=<optimized out>) at /usr/include/c++/4.8/bits/stl_vector.h:174
#3  std::vector<GeoPhysPlastWell, std::allocator<GeoPhysPlastWell> >::_M_emplace_back_aux<GeoPhysPlastWell const&> (
    this=this@entry=0x7ffd34551290) at /usr/include/c++/4.8/bits/vector.tcc:430
#4  0x00007f1b88132ac7 in push_back (__x=..., this=0x7ffd34551290) at /usr/include/c++/4.8/bits/stl_vector.h:911
#5  SpaceModel::mk_well (this=this@entry=0x15c41a0, x=10297806,168200435, y=5677090,2637730706, z_t=-50, z_b=z_b@entry=-100000, 
    dstW=..., out=out@entry=false) at src/space_model.cpp:148
#6  0x00007f1b8813af52 in MiddleModel::MiddleModel (this=0x14e7440, model=..., PV_global=..., rotate=<optimized out>, PV_local=..., 
    calc_step=..., calc_sz=..., texture_step_=..., smooth_height_=<optimized out>, z_bottom=-100000) at src/middle_model.cpp:48
#7  0x00007f1b88149a31 in _wrap_new_MiddleModel__SWIG_1 (args=<optimized out>) at spacemodel_wrap.cxx:8234
#8  _wrap_new_MiddleModel (self=<optimized out>, args=<optimized out>) at spacemodel_wrap.cxx:8296
#9  0x000000000052f936 in PyEval_EvalFrameEx ()
#10 0x000000000056d0aa in ?? ()

Мне нравится, ивдно что лег push_back. А дальше то что?;-)

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

Фобос грунт

Феерический тред, феерическое решение проблемы. Ждем следующего пуска.

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

А дальше то что?

Для начала собрать с -fsanitize=address, gcc 4.9 его поддерживает.

Потом попробовать пересобрать python с --without-pymalloc.

i-rinat ★★★★★
()
Ответ на: комментарий от AIv
struct GeoPhysPar{
//...
};

struct ZRange{ 
//...
};

struct GeoPhysPlastWell: public ZRange{ // <-- Уже не POD
//...
  GeoPhysPar par_t; // <-- Запомним тип
};

void SpaceModel::mk_well(...) {
  GeoPhysPlastWell well;
  // ...
  well.par_t = *this; // ?????????
};
AlexVR ★★★★★
()
Ответ на: комментарий от AlexVR

SpaceModel наследник GeoPhysPar.

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

А дальше то что?;-)

Насколько я могу судить, повреждены служебные данные malloc. Что конкретно делать, сказать не могу, но думаю, что push_back здесь не причем - как Женя сказал, это явно наведенная ошибка. Выше советовали санитайзеры, можно еще вызвать mcheck на входе в mk_well и после каждого calc.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Все конечно бывает, но по скромному личному опыту наведенные ошибки возникают когда запарываешь контейнер лежащий на стеке обычно в том же кадре стека, типа

int p[4];
std::vector<...> V;
p[5] = ...
и это вылезает сразу как только делаешь V\[i\] а не через млн итераций цикла. Что бы запороть W в приведенном примере...

А как его заставить раскрыть вопросики

#0  0x00007f1b8e28112f in _int_free (av=0x7f1b8e5c0760 <main_arena>, p=<optimized out>, have_lock=0) at malloc.c:3996
#1  0x00007f1b8813916a in ~base_data (this=0x7ffd34551290, __in_chrg=<optimized out>) at /usr/include/aivlib/memT.hpp:92
#2  aiv::array<float, 3>::clean (this=0x7ffd34551290) at /usr/include/aivlib/arrayTD.hpp:50
#3  0x00007ffd345512b0 in ?? ()
#4  0x00007ffd34551200 in ?? ()
#5  0x00000000014e7440 in ?? ()
#6  0x0000000000000005 in ?? ()
#7  0x0000000000000000 in ?? ()
щас он у меня в другом месте еще падает;-)

AIv ★★★★★
() автор топика
Последнее исправление: AIv (всего исправлений: 1)
Ответ на: комментарий от AIv

Все конечно бывает, но по скромному личному опыту наведенные ошибки возникают когда запарываешь контейнер лежащий на стеке обычно в том же кадре стека, типа

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

А как его заставить раскрыть вопросики

Вопросики значат, что адресу не соответствуют отладочные символы - собери программу с отладкой или поставь пакеты *-dbg (в случае python, например). Но, судя по адресам, у тебя разрушен стек, и это не поможет.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Вроде -g стоит при сборке... Т.е. то что выдает gdb при анализе core это уже наведенная ошибка - кто то до этого что то запорол, и оно по запоротому уже сегфолтнулось?

Спасибо, буду гуглить mcheck.

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

то что выдает gdb при анализе core это уже наведенная ошибка - кто то до этого что то запорол, и оно по запоротому уже сегфолтнулось?

gdb выдает финальное состояние памяти. Так что да, кто-то запортил данные malloc, и потом free рухнул на этих данных.

буду гуглить mcheck.

man mcheck же. По крайней мере, на Debian.

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

дык это то я посмотрел, я понять пытаюсь куда ее сувать... типа вызывать вначале и в конце потенциально проблемной ф-ии?

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

Я исхожу из того, что память повреждается уже из тела mk_well, так что я бы вызвал mcheck на входе в mk_well (чтобы проверить это предположение) и потом - после любого подозрительного вызова (пока что мне кажется подозрительным только calc).

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

Че то mcheck() сразу вылетает при первом же вызове... похоже питон виноват. Без питона возвращает в тесте 0, с питоном -1 ;-(

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

Неправда ваша, пыхтон ни в чем не виноват - ошибка в std::vector::emplace_back/push_back, которые «нестабильное гавно». Инфа 100%.

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

Даже если я через SWIG подключу в питон одну единственную функцию

int f(){ return mcheck(NULL); }
и вызову ее из питона, получу -1.

А просто

#include <iostream>
#include <mcheck.h>
int main(){
        std::cout<<mcheck(NULL)<<"\n";
        return 0;
}
дает 0.

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

Тогда случай слишком сложный для форумной отладки. Мне кажется, у тебя где-то double free - может, санитайзеры это найдут.

Хотя это может быть и тупо сбойной памятью - на других машинах воспроизводится?

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

У меня есть свой нетривиальный код по сборке мусора на основе подсчета ссылок, который валится на gcc-4.9 с опцией от -O2 и выше. В этом проекте он тоже используется. Но valgrind он проходил до gcc-4.7 включительно без замечаний.

На double free (если через delete []) оно же должно само ругаться? Вообще ХЗ что с этим делать, там еще куда сбоку прикручена и все это разнообразными костылями подперто...

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

Хотя это может быть и тупо сбойной памятью - на других машинах воспроизводится?

Да, но по другому;-)

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

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

это

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

У меня есть свой нетривиальный код по сборке мусора на основе подсчета ссылок, который валится на gcc-4.9 с опцией от -O2 и выше. В этом проекте он тоже используется. Но valgrind он проходил до gcc-4.7 включительно без замечаний.

Можно попробовать собрать всю фигню gcc-4.7

Хотя это может быть и тупо сбойной памятью - на других машинах воспроизводится?

Да, но по другому;-)

Оно у тебя точно однонитевое? Такое на идентичных системах должно ломаться одинаково или хотя бы очень похоже.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Там где ломается однонитевое.

На другой машине оно вроде валится в похожем месте но на другой итерации. Там не я ее запускаю, не могу точно сказать к сожалению.

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

Был бы скорей всего. push/emplace не добавляют по одному элементу, там идет типа удвоение при нехватке места. При swap эта лишняя память приходила бы в dstW.

Я имел в виду, что не было бы оверхеда на копирование объектов. Если нужно минимизировать объем занимаемой памяти в dstW, то можно было бы что-то вроде:

dstW.reserve(W.size());
dstW.insert(dstW.begin(),W.begin(),W.end());
Причем с таким insert-ом в современном C++ должно работать даже если W не является vector-ом. Или так:
W.shrink_to_fit();
dstW.swap(W);

По сути проблемы, из того что уже написали в обсуждениях напрашивается мысль о том, что ошибка наведенная. Где-то память портится, но всплывает это только вот здесь. Что уже само по себе хорошо.

Можно было бы, конечно, глянуть код функции calc на предмет того, не портится ли там стек. Но, скорее всего, путь лежит через valgrind.

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

А есть ли какой то способ (какая нить ф-я а-ля mcheck) проверить не запарывается ли стек? Ну кроме valgrind-а.

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

проверить не запарывается ли стек?

Тут почему возникают подозрения на запорченный стек: ваш временный W лежит на стеке и если вызываемый метод calc портит стек, то могут портиться данные внутри W, что и вылазит при попытке переаллоцировать буфер в W.

Но не исключено, что проблема не в порче стека, а где-то в другом месте: выход за пределы какого-то буфера при записи/модификации значений, повторный delete, обращение по битому/неинициализированному указателю...

eao197 ★★★★★
()

Неадекват

Тебе дали вполне адекватные советы, поумерь ЧСВ и научись искать ошибки в своём коде.

anonymous
()

Кстати, а переписать на rust уже предлагали?

O02eg ★★★★★
()

Вся суть сипипи в этом треде. ТС неделю теперь будет искать баг. Зато работает быстро!!11

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

И ты понимаешь почему? Или как обезьяна будешь тыкать на угад? Ты программист или где? «Программировать значит понимать».

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

Да, советовали посмотреть кору. И даже спрашивали, что там.

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

Простите что повторяюсь - можно я сам буду решать что и как мне делать?;-)

Хуже невежества убежденное невежество...

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

man научит. Гугл, в конце концов.

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

силён ты с умным видом чушь пороть :)

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

Я туплю. Итак, gcc 4.7.2 От такой простой пример:

#include <stdio.h>

void f(const int &a){
        int p[1]; 
        printf("&a-p=%ld\n", &a-p);
        p[&a-p] = 2;
}

int main(){
        int a = 1;
        f(a);
        printf("a=%i\n", a);
        return 0;
}
Собираем-запускаем:
$ g++ -Wall test.cpp && ./a.out 
&a-p=11
a=2
$ g++ -Wall -fstack-protector-all test.cpp && ./a.out 
&a-p=9
a=2
$ valgrind ./a.out
...
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2
Ы?

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv
#include <stdio.h>

void f(const int * a) {
	int b[8];
	printf("b=%p\n", &b);

	for( int * c = b; c < a; ++c )
		*c = 0;
}

void g() {
	int a[8];
	printf("a=%p\n", &a);
	f(a);
}

int main(){
	g();
        return 0;
}

Компиляция с ключами «g++ -Wextra -fstack-protector-strong» При запуске получаем:

a=000000000023FE10
b=000000000023FDD0
*** stack smashing detected ***:  terminated

Если заменить -fstack-protector-strong на -fstack-protector, то будет простой сегфолт без сообщения о stack smashing. Ключ -fstack-protector работает только для функций, в которых есть буфера char-ов или обращения к alloca. Попробуйте в показанном мной коде заменить int на char и ошибка stack smashing detected будет показана даже с -fstack-protector. Но у -fstack-protector есть еще одна особенность — генерация проверки целостности стека включается только если есть буфера от 8 байт и больше. В принципе, все это рассказывается в документации к GCC.

Так же нужно понимать, что эти опции не включают какой-то волшебной защиты стека. Они лишь заставляют добавлять в стек специальную дополнительную переменную. Содержимое которой затем проверяется. Если содержимое переменной нарушено, значит была попытка выйти за пределы стека в вызванной функции.

Однако, если точно указать адрес внутри стека вызывающей функции, как в вашем случае, то содержимое специальной переменной не изменится. Поэтому stack smashing не диагностируется.

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

Начигает доходить, спасибо большое:-)

Т.е. если стек порется не прицельно а «по площадям» то он это может поймать (т.к. цепляет эту спец. переменную)?

Как это отражается на производительнсоти и как взаимодействует с -О3?

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

Кому-то просто лень читать документацию - ведь гораздо проще заявить, что «std::vector::emplace_back/push_back нестабильное гавно» :)

Дополнительно можно посоветовать ТС добавить при сборке (debug) ключики -fsanitize=address -fno-omit-frame-pointer -g.

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

Т.е. если стек порется не прицельно а «по площадям» то он это может поймать (т.к. цепляет эту спец. переменную)?

Типа того.

Как это отражается на производительнсоти

Дополнительные push/pop + проверки на каждый вызов функции. Влияние на производительность сильно зависит от «тяжести» самих функций.

и как взаимодействует с -О3?

Понятия не имею.

Вам имеет смысл ознакомиться хотя бы вот с этим.

Ну и тут вот ниже уже дали хороший совет на счет -fsanitize=address -fno-omit-frame-pointer -g.

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