![]() |
|
Модераторы: xvr |
![]()
|
|
| Kwal |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
Столкнулся с интересной проблемой. Лет 6 назад использовал одну прогу под ASPLinux 7.2. Исходники компилировались нормально и прога работала (gcc был, по-моему, версии 2.95).
Сейчас появился интерес реанимировать этот проект, но уже под Russian Fedora 12. Компиляция и установка прошли нормально (правда пришлось установить compat-gcc-3.4.2) , но при запуске программа выдала «Segmentation fault». Исследование проблемы показало, что сбой происходит на , казалось бы, абсолютно нормальном участке кода: CFilter* f = new CFilter; Filters.push_back(f); <-------- здесь! Причем CFilter — некий класс, потомок класса CFilterBase, а Filters является вектором: class CFilters : public vector<CFilterBase*>. Вроде все нормально. Поиски корней проблемы привели к следующему. Оказывается, содержимое Filters портится при выполнении следующей команды: string libfile = dblib_paths[i] + "lib" + DBType + "db.so"; где dblib_paths — vector (количество элементов — 1, i=0), DBType — string, т.е. std::string DBType; vector<string> dblib_paths. Причем происходит следующее. dblib_paths и Filters располагаются в памяти друг за другом. При выполнении этой строчки происходит пристыковка "/lib" + DBType + "db.so" к dblib_paths непосредственно в месте ее расположения и потом присвоение адреса этой области памяти переменной libfile. Причем пристыковка залезает на область памяти, занимаемой Filters, что впоследствии и приводит к сбою программы. После выполнения этой строчки libfile располагается там же, где был dblib_paths[0]. Хотя, по логике, при присвоении переменной класса string должно происходить копирование объекта. Т.е. менеджер памяти должен отслеживать ситуацию. Моделирование данной ситуации на простой программе показало, что действительно, менеджер памяти отслеживает эту ситуацию и при выполнении такой же строчки происходит копирование содержимого dblib_paths в свободную область памяти и там уже происходит пристыковка всего остального. И libfile имеет уже другой адрес, чем dblib_paths. Вопрос: почему так происходит? Почему раньше (на ASPLinux 7.2) эта прога работала, а теперь, в более новой версии Linux'а — такие косяки? Что-то с реализацией класса string? Или ключи какие надо установить? Сделал strace -v -olog.txt ./proga. вот этот самый кусок: mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78e1000 Здесь я вывожу свойства Filters, который потом портится write(1, "1.Filters: empty=1 capacity=0 size=0 max_size=1073741823\n", 48) = 48 write(1, "2.Filters: empty=1 capacity=0 size=0 max_size=1073741823\n", 48) = 48 Вот здесь эта строчка : string libfile = dblib_paths[i] + "/lib" + DBType + "db-" VERSION ".so"; write(1, "3.Filters: empty=0 capacity=-191917709 size=29360180 max_size=1073741823\n", 64) = 64 ВСЁ! Filters испортился! write(1, " ---> /usr/local/aspseek/lib/libmysqldb-1.2.15.so\n", 50) = 50 <---- вывод содержимого libfile write(1, "libfile: empty=0 capacity=1073741824 size=43 max_size=1073741820\n", 63) = 63 write(1, "4.Filters:empty=0 capacity=-191917709 size=29360180 max_size=107374182"..., 66) = 66 futex(0xc08068, FUTEX_WAKE_PRIVATE, 2147483647) = 0 open("/usr/local/aspseek/lib/libmysqldb-1.2.15.so", O_RDONLY) = 3 ......... А вот здесь уже происходит обращение Filters.push_baсk(f); Как видно свойства Filters больше не меняются write(1, "Filters:empty=0 capacity=-191917709 size=29360180 max_size=1073741823\n", 62) = 62 --- SIGSEGV (Segmentation fault) @ 0 (0) --- write(2, "Address of param: bf802e70\n", 27) = 27 sigreturn() = ? (mask now []) --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV (core dumped) +++ P.S. Предвидя вопросы типа где makefile, версия gcc и т.п. скажу, что прога эта - поисковая машина aspseek (www.aspseek.org), там все исходники. |
|||
|
||||
| нуп |
|
||||
|
Ботокодер ![]() ![]() Профиль Группа: Участник Сообщений: 987 Регистрация: 22.6.2009 Где: Кременчуг Репутация: нет Всего: 33 |
Даже такое нельзя написать
|
||||
|
|||||
| Kwal |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
А вот так можно:
т.к. сначала идет сложение, а потом присвоение. Добавлено через 1 минуту и 55 секунд А иначе нафига вообще string нужны |
||||||
|
|||||||
| borisbn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 4875 Регистрация: 6.2.2010 Где: Ростов-на-Дону Репутация: нет Всего: 135 |
1. Абсолютно уверен, что dblib_paths не пустой, и i==0 ?
2. В define VERSION нет знака равенства ? 3. Разбей эту строку на составляющие и выводи Filters после каждого шага -------------------- Женщины отличаются от программистов тем, что у них чары состоят из стрингов |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: нет Всего: 110 |
есть несколько направлений поиска:
1. раз простая программа работает правильно, а сложная неправильно, один из вариантов - постепенно преобразовывать сложную к простой, т.е. удалять код постепенно и смотреть на проявление бага, рано или поздно найдётся изменение, которое "включает/выключает" баг, если не будет понятно почему - удалять всё остальное, пока не будет понятно. 2. если под отладчиком баг воспроизводится - пройтись по этому месту, залезть в исходники string::operator+ и string::operator= и посмотреть, что он там делает не так, при этом лучше (по возможности) 3. проверить, а не удалил/испортил ли кто-то Filters до этого места в программе - в этом случае string может просто рассматривать эту память, как свободную -------------------- qqq |
|||
|
||||
| xvr |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 20 Всего: 223 |
90% - проблема в балансе new/delete. Прогони прогу под valgrind
Это сообщение отредактировал(а) xvr - 25.3.2010, 11:32 |
|||
|
||||
| MAKCim |
|
|||
![]() Воін дZэна ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5644 Регистрация: 10.12.2005 Где: Менск, РБ Репутация: 84 Всего: 207 |
однозначно компилировать надо с отладочной инфой и прогонять под valgrind'ом
обычно все проблемы с памятью решаются за 5 минут скажу по секрету, 99(9)%, что проблема у вас ;) -------------------- Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі © |
|||
|
||||
| Kwal |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 3 Регистрация: 25.3.2010 Репутация: нет Всего: нет |
Ошибка найдена!!!
Как и ожидалось, именно в программе, а не в string Причина - в грубом вмешательстве в работу класса string через изменение статического члена класса через дальний указатель. Видимо, это работало под ранними версиями Linux, а впоследствии, может быть, программная реализация класса слегка изменилась. Правда пока не совсем понятно, зачем это надо было делать. Вот что написано в комментах:
Помог метод приведения программы к простой (метод исключения). Всем спасибо за советы!!! |
|||
|
||||
![]()
|
| Правила форума "С/С++: Программирование под Unix/Linux" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |