URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 7042
[ Назад ]

Исходное сообщение
"pqxx, оптимизация и Segmentaion fault"

Отправлено crnz , 17-Дек-07 14:27 
Добрый день.
Имеется программа использующая несколько разделяемых библиотек (boost, stlport и др...) и, в том числе, pqxx.
Если программу собирать с флагом -O2, то все работает замечательно, а вот если с -O0 то она будет падать с Segmentation Fault и в стеке будет следующее:

#0  0x001b043e in malloc_consolidate () from /lib/tls/libc.so.6
#1  0x001afa59 in _int_malloc () from /lib/tls/libc.so.6
#2  0x001aedfd in malloc () from /lib/tls/libc.so.6
#3  0x00e3183f in makeEmptyPGconn () at fe-connect.c:1839
#4  0x00e300fe in PQconnectStart (conninfo=0x0) at fe-connect.c:321
#5  0x00e300c2 in PQconnectdb (conninfo=0x0) at fe-connect.c:286
#6  0x0819ee10 in connection (this=0x9715174, ConnInfo=0x9714530 "dbname=...") at ../include/pqxx/connection_base.hxx:187
...

Хотелось бы понять почему так происходит и как это исправить?


Содержание

Сообщения в этом обсуждении
"pqxx, оптимизация и Segmentaion fault"
Отправлено Michelnok , 17-Дек-07 15:49 
>
>Хотелось бы понять почему так происходит и как это исправить?

1. Скорее всего ошибка не связана с malloc, т.к. на всех остальных миллионах компьютеров malloc работает нормально.
2. Скорее всего ошибка не связана с libpq++, т.к. валится все-таки в malloc.

Вывод - кто-то портит память, malloc работает с уже запорченной кучей. Маловероятно что это из-за оптимизации компилятора. Просто в случае -O2 _последствия_ получаются несколько иными (из-за иной раскладки страниц кода и данных) и в данном месте нет падения.
Ищите кто кучу портит.


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 17-Дек-07 16:05 
>Ищите кто кучу портит.

а как можно найти того кто портит кучу?
есть ли инструменты для этого?


"pqxx, оптимизация и Segmentaion fault"
Отправлено Michelnok , 17-Дек-07 17:13 
>есть ли инструменты для этого?

Да, куча всяких. Первое что попадается на глаза - Electric Fence


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 17-Дек-07 18:35 
>>есть ли инструменты для этого?
>
>Да, куча всяких. Первое что попадается на глаза - Electric Fence

спасибо. попробую


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 17-Дек-07 19:35 
>Да, куча всяких. Первое что попадается на глаза - Electric Fence

Electric Fence ничего не показывает. Программа просто сваливается в coredump в разных местах точно так же как и без него...


"pqxx, оптимизация и Segmentaion fault"
Отправлено DeadMustdie , 17-Дек-07 21:44 
Я бы попробовал valgrind'ом ковырнуть

"pqxx, оптимизация и Segmentaion fault"
Отправлено Alu , 18-Дек-07 08:12 
>Electric Fence ничего не показывает. Программа просто сваливается в coredump в разных
>местах точно так же как и без него...

именно так же? Принцип работы Efence - валиться в случае прострела в память...
А Valgrind действительно хорошая штука. Смотрите в логе Invalid write'ы и Invalid read'ы


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 18-Дек-07 11:40 
>именно так же? Принцип работы Efence - валиться в случае прострела в
>память...

именно что также, как будто Efencа и в помине нет...

>А Valgrind действительно хорошая штука. Смотрите в логе Invalid write'ы и Invalid
>read'ы

Да, действительно они есть:

==9480== Invalid read of size 4
==9480==    at 0x4266901: __pthread_mutex_unlock_usercnt (in /lib/tls/libpthread-0.60.so)
==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)
==9480==    by 0x806B448: CCriticalSectionHolder::unlock() (CriticalSection.h:73)
...
==9480==  Address 0xBEFFA00D is just below the stack ptr.  To suppress, use: --workaround-gcc296-bugs=yes

==9480== Invalid write of size 4
==9480==    at 0x426690E: __pthread_mutex_unlock_usercnt (in /lib/tls/libpthread-0.60.so)
==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)
...

==9480== Syscall param futex(futex) points to unaddressable byte(s)
==9480==    at 0x4269791: __lll_mutex_unlock_wake (in /lib/tls/libpthread-0.60.so)
==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)
==9480==    by 0x806B448: CCriticalSectionHolder::unlock() (CriticalSection.h:73)
...
==9480==  Address 0xBEFFA001 is not stack'd, malloc'd or (recently) free'd

как понять почему так получается?
и что означают загадочные строчки "Address 0xBEFFA00D is just below the stack ptr", "Address 0xBEFFA001 is not stack'd, malloc'd or (recently) free'd"?

а вот финальный аккорд на безобидном std::map::find():
==9480== Invalid read of size 4
==9480==    at 0x8067D28: _STL::_Rb_tree_node<_STL::pair<_STL::basic_string<...
==9480==    by 0x80673B3: _STL::_Rb_tree_iterator<_STL::pair<_STL::basic_string<...
==9480==    by 0x8066884: _STL::map<_STL::basic_string<char, _STL::char_traits<...
==9480==    by 0x80645F4: main
==9480==  Address 0xAC is not stack'd, malloc'd or (recently) free'd
==9480==
==9480== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==9480==  Access not within mapped region at address 0xAC


"pqxx, оптимизация и Segmentaion fault"
Отправлено Alu , 19-Дек-07 09:37 
>==9480== Invalid read of size 4
>==9480==    at 0x4266901: __pthread_mutex_unlock_usercnt (in /lib/tls/libpthread-0.60.so)
>==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)
>==9480==    by 0x806B448: CCriticalSectionHolder::unlock() (CriticalSection.h:73)

Скорее всего проблема в адресе переменной типа pthread_mutex_t, которая передаётся pthread_mutex_unlock(). Адрес этот битый. Ищите проблему начиная с обёртки для мьютекса(CCriticalSectionHolder).

>==9480== Invalid write of size 4
>==9480==    at 0x426690E: __pthread_mutex_unlock_usercnt (in /lib/tls/libpthread-0.60.so)
>==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)

Проявление той же проблемы.

>==9480== Syscall param futex(futex) points to unaddressable byte(s)
>==9480==    at 0x4269791: __lll_mutex_unlock_wake (in /lib/tls/libpthread-0.60.so)
>==9480==    by 0x426697F: pthread_mutex_unlock (in /lib/tls/libpthread-0.60.so)
>==9480==    by 0x806B448: CCriticalSectionHolder::unlock() (CriticalSection.h:73)

Проявление той же проблемы.
>==9480==  Address 0xBEFFA001 is not stack'd, malloc'd or (recently) free'd

Адрес связанный с вышеописанной проблемой пренадлежит ни стеку, ни  куче. Т.е. имеет место прострел.

>как понять почему так получается?

Отлаживать :)  Внимательно проследить цикл жизни проблемных объектов, включая копирование.

>и что означают загадочные строчки "Address 0xBEFFA00D is just below the stack ptr"

Адрес располжен ниже указателя стека. Т.е. Той области, до которой стек не дорос. Часто такое бывает при выделении объекта на стеке внутри функции и последующей попытке использовать его вне этой функции.

>, "Address 0xBEFFA001 is not stack'd, malloc'd or (recently) free'd"?

Адрес связанный с вышеописанной проблемой пренадлежит ни стеку, ни  куче.

>[оверквотинг удален]
>==9480== Invalid read of size 4
>==9480==    at 0x8067D28: _STL::_Rb_tree_node<_STL::pair<_STL::basic_string<...
>==9480==    by 0x80673B3: _STL::_Rb_tree_iterator<_STL::pair<_STL::basic_string<...
>==9480==    by 0x8066884: _STL::map<_STL::basic_string<char, _STL::char_traits<...
>==9480==    by 0x80645F4: main
>==9480==  Address 0xAC is not stack'd, malloc'd or (recently) free'd
>==9480==
>==9480== Process terminating with default action of signal 11 (SIGSEGV): dumping core
>
>==9480==  Access not within mapped region at address 0xAC

Так как мап хранит копии объектов, думаю проблема в нём самом. Проследите его жизненный цикл.
Удачи.



"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 19-Дек-07 13:45 
спасибо за помощь!
буду разбираться...


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 19-Дек-07 17:14 
стал внимательнее смотреть как собирается проект, и как собирались библиотеки к нему,
увидел что одна из библиотек (как раз та, где сидит обертка к мьютексу) собиралась с ключом
-D_GNU_SOURCE

пересобрал проект с этим же ключом - все заработало, все проблемы исчезли.

что за чудеса? GNUшный стандарт компиляции так сильно отличается от того что по умолчанию?


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 19-Дек-07 17:21 
>[оверквотинг удален]
>
>увидел что одна из библиотек (как раз та, где сидит обертка к
>мьютексу) собиралась с ключом
>-D_GNU_SOURCE
>
>пересобрал проект с этим же ключом - все заработало, все проблемы исчезли.
>
>
>что за чудеса? GNUшный стандарт компиляции так сильно отличается от того что
>по умолчанию?

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


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 26-Дек-07 16:08 
Разобрался.

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

Спасибо всем за помощь.



"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 26-Дек-07 17:01 
>Проблема заключалась в том, что было два разных класса с одним названием
>CCriticalSection (один в программе, а один в разделяемой библиотеке).

Кстати, а есть ли способ заставить компилятор ругаться на такие ситуации, или это только вручную можно отследить?


"pqxx, оптимизация и Segmentaion fault"
Отправлено Michelnok , 26-Дек-07 19:19 
>Кстати, а есть ли способ заставить компилятор ругаться на такие ситуации...?

Вряд ли. Компилятор не знает чего вы хотите, он лишь транслирует код. Может вы хотите именно разные классы использовать?


"pqxx, оптимизация и Segmentaion fault"
Отправлено DeadMustdie , 27-Дек-07 10:03 
>Кстати, а есть ли способ заставить компилятор ругаться на такие ситуации, или
>это только вручную можно отследить?

К сожалению, описанная проблема может быть отловлена в лучшем случае линкером, а в худшем - никем.
Линкер из GNU binutils способен поймать описанную проблему в случае, когда библиотека явно "линкуется" с основной программой и "одноименный" класс имеет хотя бы один не-inline метод. Прочие ситуации - на совести программиста.


"pqxx, оптимизация и Segmentaion fault"
Отправлено Arifolth , 27-Дек-07 17:17 
>>Проблема заключалась в том, что было два разных класса с одним названием
>>CCriticalSection (один в программе, а один в разделяемой библиотеке).
>
>Кстати, а есть ли способ заставить компилятор ругаться на такие ситуации, или
>это только вручную можно отследить?

если ваш класс будет сидеть в своём пространстве имён, и для доступа к нему будет использоваться full qualified name - может быть проблема решиться сама собой?


"pqxx, оптимизация и Segmentaion fault"
Отправлено crnz , 28-Дек-07 16:10 
>если ваш класс будет сидеть в своём пространстве имён, и для доступа
>к нему будет использоваться full qualified name - может быть проблема
>решиться сама собой?

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


"pqxx, оптимизация и Segmentaion fault"
Отправлено DeadMustdie , 28-Дек-07 16:43 
>а чем это отличается от переименования класса?

Ничем не отличается.

>проблема была в том, что я не знал, что есть два класса
>с одинаковым именем

В стандарте C++ сие именуется "one definition rule" и, по сути дела,
оставлено на откуп программиста. Пригодных к использованию инструментов
для автоматизации решения такого рода задач (в принципе, смежных с
рефакторингом) для C++ я, увы, не видел.