Программа вылетакет по Segmentation Fault (Как искать причину?)

Модератор: Модераторы разделов

MiK13
Сообщения: 1292
ОС: Linux Debian

Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

Есть довольно большой проект (не мой). Написанный (и при этом хорошо работающий) на борландовском билдере (под Windows). Необходимо перенести его под Linux.
Более того, эта же программа тоже работает после трансляции под Debian Sarge. А после перехода на Debian Etch после сборки и запуска программа вылетает с вышеуказанной ошибкой.
Путём установок операторов printf выяснилось следующее:
В одном модуле:

Код: Выделить всё

   printf("Addr(WCP_ALL) = %p\n",&WCP_ALL);
   WCP_ALL.ReadOutFile("PARAM_VTOR.param");
   printf("Addr(WCP_ALL) = %p\n",&WCP_ALL);

выдаёт:
Addr(WCP_ALL) = 0xbf8fcb47
Addr(WCP_ALL) = 0x81d84c7
Т.е. изменяется адрес переменной (точнее, структуры) WCL_ALL
После установки операторов печати в функцию :

Код: Выделить всё

void WRTE_ControlParam::ReadOutFile(char *SF) {
  try {
    ifstream is( SF );
    if( is.is_open() ) {
      is >> Header    ;  // Идентификатор пакета
        printf(" Header = %u, &%p\n",Header,&Header);
      is >> ALLPramVtor;  // число бланков в структуре до 25
    }
  }
  catch(...) {
    puts(" Явная проблема -- Файл не был создан");
  }
  printf(" Header = %u, &%p\n",Header,&Header);
  ///// printf(" Addr(WRTE_ControlParam::ReadOutFile) = %p\n",&WRTE_ControlParam::ReadOutFile);
};

Получается результат:
Addr(WCP_ALL) = 0xbfe738c7
Header = 0, &0xbfe738c7
Header = 0, &0xbfe738c7
Addr(WCP_ALL) = 0x81d84c7
(Header -- первый элемент WCL_ALL)
Ещё один интересный момент: Если раскомментировать строку печати (перед которой /////), то результат вывода получается следующий:
Addr(WCP_ALL) = 0xbfd7bfc7
Header = 0, &0xbfd7bfc7
Header = 0, &0xbfd7bfc7
Addr(WRTE_ControlPramVtor_ALL::ReadOutFile) = 0x80b12dc
Addr(WCP_ALL) = 0xbfd7bfc7
Т.е. адрес WCP_ALL уже не изменяется. Но программа вылетает в другом месте.
Я ничего не понимаю. Автор программы уверяет, что придерживался стандарта языка.
В системе стоит компилятор gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
У меня как-то не укладывается в голове мысль, что причина может быть в нём и что компилятор версии 3.3 транслирует нормально.

И ещё такой момент: при трансляции большинства файлов выскакивает довольно много предупреждений типа:
warning: 'class AAAAA' has virtual functions but non-virtual destructor
Автор уверяет, что это нормально и на это не надо обращать внимания.
Можно ли избавиться именно от этих предупреждений, если задан ключ -Wall ? (этот ключ я стал добавлять после того, как в конце комментария случайно оказался знак \ и следующая строка не компилировалась. А ни FARовский плагин расцветки, ни редактор миднайт командера не показывали, что следущая строка тоже закоментирована.
Спасибо сказали:
yaleks
Сообщения: 2121
Статус: вне статуса
ОС: Gentoo ~

Re: Программа вылетакет по Segmentation Fault

Сообщение yaleks »

strace пробовали?
Спасибо сказали:
Serg79
Сообщения: 153

Re: Программа вылетакет по Segmentation Fault

Сообщение Serg79 »

Попробуй добиться компилирования проекта без warning-ов тогда прога перестанит падать с вероятностью 90%. Это значит приводить код в соответствие со стандартом.

Такие проблемы (Segmentation Fault) довольно часто возникают когда начинаешь переносить прогу с 32-разрядной платформы на 64-разрядную.
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: Программа вылетакет по Segmentation Fault

Сообщение nesk »

yaleks писал(а):
23.07.2008 16:25
strace пробовали?

strace тут явно не поможет!! ведь проблема в обращении к непроинициализированой ячейки памяти.
Тут надо брать в руки настоящий отладчик gdb (можно с графическим фронт-эндом), расставить контрольные точки и смотреть, где и почему реально происходит нарушение сегментации
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

yaleks писал(а):
23.07.2008 16:25
strace пробовали?

Пробовал. Только толку... Он выдаёт список выполняющихся системных вызовов. А вот в какой момент и почему изменяется адрес переменной (который, по идее, дожен жёстко задаваться в коде программы) я не представляю как узнать.

Хотя...
Сейчас попробовал ещё раз и заинтересовало начало программы:
brk(0) = 0x81db000
brk(0x81db820) = 0x81db820
set_thread_area({entry_number:-1 -> 6, base_addr:0x81db808, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
brk(0x81fc820) = 0x81fc820
brk(0x81fd000) = 0x81fd000

Что такое set_thread_area ? В программе никакой многопоточности нет. Или это какие-то особенности C++?
И последнее, что выдала эта программа было:

Код: Выделить всё

write(1, " Header = 0, &0xbfcf2737\n", 25 Header = 0, &0xbfcf2737
) = 25
write(1, "Addr(WCP_ALL) = 0x81d84c7\n", 26Addr(WCP_ALL) = [u]0x81d84c7[/u]
) = 26
write(1, "SecondariProces::Secondari"..., 68SecondariProces::SecondariProces 11, &WCP_ALL=0x81d84c7
) = 68
write(1, "SecondariProces::SetParame"..., 53SecondariProces::SetParametrSecondariProces  0
) = 53
write(1, "   0: byte 0 from 0x81d84c7 to 0"..., 41   0: byte 0 from 0x81d84c7 to 0x818ed8f
) = 41
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Process 30470 detached

Некоторый комментарий к выводу.
После печати изменённого значения адреса переменной вызывается ещё одна функция. После неё идёт ещё один контрольный вывод, показывающиё тоже значение адреса переменной WCL_ALL.
Затем вызывается функция SetParametrSecondariProces( WCP_ALL );
В ней принимается параметр по ссылке и затем эта структура копируется в другую. И программа при этом копировании вылетает. Вот начало этой функции:

Код: Выделить всё

void SecondariProces::SetParametrSecondariProces(WRTE_ControlParam &P) {
  unsigned char *ap1 = (unsigned char *)&P, *ap2=(unsigned char *)&PARAM_VTOR;
  unsigned iiii;
      puts("SecondariProces::SetParametrSecondariProces  0");
  for(iiii=0;iiii<sizeof(PARAM_VTOR);iiii++) {
    if(iiii<5)
      printf(" %3d: byte %d from %p to %p\n",iiii,ap1[iiii],ap1+iiii,ap2+iiii);
    fflush(stdout);
    ap2[iiii]=ap1[iiii];
  }
      puts("SecondariProces::SetParametrSecondariProces  1");
  // PARAM_VTOR = P;

Первоначально в нём были только первая и последняя строки из этого фрагмента. Остальные были добавлены, чтобы найти место, где программа вылетает, В данном случае оказалось, что она вылетает при попытке скопировать содержимое области формального параметра P в область PARAM_VTOR, адрес которой тоже изменился и стал (как я понимаю) в области адресов памяти доступной тольк для чтения. Но вот как могла случиться, что изменились адреса переменных?
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

Serg79 писал(а):
23.07.2008 18:39
Попробуй добиться компилирования проекта без warning-ов тогда прога перестанит падать с вероятностью 90%. Это значит приводить код в соответствие со стандартом.
Я (после указанного в начале случая) стал компилировать програииы с ключом -Wall и добиваться отсутствия warning'ов. Но вся проблема в том, что эту программу писал не я и её автор утверждает, что их наличие не должно никак влиять на работоспособность программы (тем более, что в Sarge она не вылетает (по крайней мере запускается, а долго мы не проверяли).
Serg79 писал(а):
23.07.2008 18:39
Такие проблемы (Segmentation Fault) довольно часто возникают когда начинаешь переносить прогу с 32-разрядной платформы на 64-разрядную.

Но в данном случае надо перенести программу из Windows (Borland C-Builder) в Linux, с компилятором gcc и g++ на тоже 32-разрядную систему.
nesk писал(а):
23.07.2008 18:46
Тут надо брать в руки настоящий отладчик gdb (можно с графическим фронт-эндом), расставить контрольные точки и смотреть, где и почему реально происходит нарушение сегментации

Так случилось, что мне ещё ни разу не приходилось пользоваться этим отладчиком.
Но попробую.
Спасибо сказали:
yaleks
Сообщения: 2121
Статус: вне статуса
ОС: Gentoo ~

Re: Программа вылетакет по Segmentation Fault

Сообщение yaleks »

MiK13 писал(а):
23.07.2008 16:06
Я ничего не понимаю. Автор программы уверяет, что придерживался стандарта языка.
В системе стоит компилятор gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
У меня как-то не укладывается в голове мысль, что причина может быть в нём и что компилятор версии 3.3 транслирует нормально.

Это вы ещё GCC 4.3 не пробовали - он ещё строже проверяет соответствие стандарту.
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

Разобрался кое-как с отладчиков. И вот что получил.
Сначала выяснил, что при выполнении оператора ifstream is( SF ) разрушается стек. Т.е. до его выполнния команда bt выдаёт три строки, а после его -- две и говорит о предположительном разрушении стека.
Разбивка этого оператора на 2:
ifstream is;
is.open(SF);
не помогла. Помогло добавление слова static перед ifstream.
Но вот с выводом файла (т.е. с ofstream) и это не помогло:

Код: Выделить всё

Breakpoint 1, WRTE_ControlParam::SaveInFile (this=0xbfd6904f, SF=0x81895d2 "PARAM_VTOR.param") at StructExchangeDataNet.cpp:625
625       printf("WRTE_ControlParam::SaveInFile \n");
(gdb) s
WRTE_ControlParam::SaveInFile
627           static ofstream of;
(gdb) bt
#0  WRTE_ControlParam::SaveInFile (this=0xbfd6904f, SF=0x81895d2 "PARAM_VTOR.param") at StructExchangeDataNet.cpp:627
#1  0x080599cb in SecondariProces::SetParametrSecondariProces (this=0xbfd68fe8, P=@0xbfd68787) at SecondariProcessing.cpp:1384
#2  0x0805c65e in SecondariProces (this=0xbfd68fe8, Range=450, T=1.8) at SecondariProcessing.cpp:770
#3  0x080cd360 in main (argn=1, argv=0xbfd69664) at prog_main.cpp:83
(gdb) s
628           std::ios_base::openmode om = std::ios_base::trunc;
(gdb) bt
#0  WRTE_ControlParam::SaveInFile (this=0xbfd6904f, SF=0x81895d2 "PARAM_VTOR.param") at StructExchangeDataNet.cpp:628
#1  0x080599cb in SecondariProces::SetParametrSecondariProces (this=0xbfd68fe8, P=@0xbfd68787) at SecondariProcessing.cpp:1384
#2  0x0805c65e in SecondariProces (this=0xbfd68fe8, Range=450, T=1.8) at SecondariProcessing.cpp:770
#3  0x080cd360 in main (argn=1, argv=0xbfd69664) at prog_main.cpp:83
(gdb) s
629           of.open( SF, om );
(gdb) bt
#0  WRTE_ControlParam::SaveInFile (this=0xbfd6904f, SF=0x81895d2 "PARAM_VTOR.param") at StructExchangeDataNet.cpp:629
#1  0x080599cb in SecondariProces::SetParametrSecondariProces (this=0xbfd68fe8, P=@0xbfd68787) at SecondariProcessing.cpp:1384
#2  0x0805c65e in SecondariProces (this=0xbfd68fe8, Range=450, T=1.8) at SecondariProcessing.cpp:770
#3  0x080cd360 in main (argn=1, argv=0xbfd69664) at prog_main.cpp:83
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x080d7a93 in std::basic_ofstream<char, std::char_traits<char> >::open ()
(gdb)

Т.е. при попытке открыть файл программа вылетает. Файл при этом оказывается нулевой длины. Т.е. начальный этап открытия происходит.
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

yaleks писал(а):
23.07.2008 20:52
MiK13 писал(а):
23.07.2008 16:06
Я ничего не понимаю. Автор программы уверяет, что придерживался стандарта языка.
В системе стоит компилятор gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
У меня как-то не укладывается в голове мысль, что причина может быть в нём и что компилятор версии 3.3 транслирует нормально.

Это вы ещё GCC 4.3 не пробовали - он ещё строже проверяет соответствие стандарту.

Действительно не пробовал :) Лежит он у меня скачанный в виде tar.gz архива, но я пока не представляю, как его ставить (и стоит ли?)
Но меня больше интересует не строгость проверки на соответствие стандарту, а корректность странсляции.
Как я уже написал перед этим, проблемы возникали при работе с потоком ввода и вывода. Хотя простейший пример:

Код: Выделить всё

// opening and closing a file
#include <iostream.h>
#include <fstream.h>
using namespace std;

int main () {

  ofstream outfile;
  outfile.open ("test.txt");
  outfile << "Test 2";
  // >> i/o operations here <<
  outfile.close();
  return 0;
}

отработал нормально
Спасибо сказали:
Аватара пользователя
halturin
Сообщения: 167
ОС: Linux

Re: Программа вылетакет по Segmentation Fault

Сообщение halturin »

До тех пор, пока автор не покажет полный код, все это обсуждение сродни гаданию на кофейной гуще.

PS: а слова типа SecondariProces говорят про потоки? если да, то есть подозрение что грабли где-то здесь.
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

halturin писал(а):
23.07.2008 23:05
До тех пор, пока автор не покажет полный код, все это обсуждение сродни гаданию на кофейной гуще.

Исходный код у меня есть. Проблема в том, что нет возможности постоянно контактировать с автором. Да и он уверяет, что у него всё нормально. Хотя бы на основании того, что на билдере программа работает без проблем. Более того, похоже, что и на 3-м Дебиане (Sarge) она тоже работает.
Подозреваю, что проблема может быть в том, что в коде очень много операторв типа ofstream& operator<<(ofstream& os, ... и ifstream& operator>>(ifstream& is,, очень много разных классов
halturin писал(а):
23.07.2008 23:05
PS: а слова типа SecondariProces говорят про потоки? если да, то есть подозрение что грабли где-то здесь.

Потокок есть, но не программный -- поступает поток данных от измерительного устройства и на его основе формируется выходной поток

А как избавиться от предупреждений типа 'class AAA' has virtual functions but non-virtual destructor ?
Спасибо сказали:
Аватара пользователя
Skladnoy
Сообщения: 90
ОС: Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение Skladnoy »

MiK13 писал(а):
23.07.2008 22:11
Сначала выяснил, что при выполнении оператора ifstream is( SF ) разрушается стек. Т.е. до его выполнния команда bt выдаёт три строки, а после его -- две и говорит о предположительном разрушении стека.
Разбивка этого оператора на 2:
ifstream is;
is.open(SF);
не помогла. Помогло добавление слова static перед ifstream.
Но вот с выводом файла (т.е. с ofstream) и это не помогло:

1. Что такое SF?
2. Где происходит разрушение стека во втором варианте?
3. Прозреваю извращённое повреждение памяти. Попробуйте натравить valgrind

P.S. Добавление statiс изменяет семантику программы. Низзя так


P.P.S.
MiK13 писал(а):
24.07.2008 10:29
Исходный код у меня есть.

Сюда покажет.
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

Skladnoy писал(а):
24.07.2008 13:18
1. Что такое SF?
2. Где происходит разрушение стека во втором варианте?
3. Прозреваю извращённое повреждение памяти. Попробуйте натравить valgrind

P.S. Добавление statiс изменяет семантику программы. Низзя так

1-> SF -- обычный char *, содержит имя файла, который надо открыть. пdb показывает его правильно.
2-> Я так и не понял. Сразу после выполнения команды s в gdb возникал SIGSEGV. Что и как анализировать дальше, пока не знаю
3-> За рекомендаций valgrind спасибо. Поставлю его и поразбираюсь с ним.

P.S. -> static уберу и постараюсь выяснить, в чём причина (надеюсь на valgrind)
Спасибо сказали:
Аватара пользователя
Skladnoy
Сообщения: 90
ОС: Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение Skladnoy »

Стек разрушается после ifstream is; или is.open(SF); ?

MiK13 писал(а):
24.07.2008 10:29
А как избавиться от предупреждений типа 'class AAA' has virtual functions but non-virtual destructor ?

Сделать деструктор виртуальным.
См. далее: http://www.parashift.com/c++-faq-lite/virt...s.html#faq-20.7
Спасибо сказали:
Аватара пользователя
Electronix
Сообщения: 53
ОС: Slackware, Suse, XP

Re: Программа вылетакет по Segmentation Fault

Сообщение Electronix »

Под линуксом нужно собрать приложение с опцией -g (для поддержки дебаговой информации).
Затем запустить ulimit -c 99999999.
Запустить приложение и вызвать seg fault.
Будет сгененирован дамп памяти.
gdb <имя бинарника> <имя core файла который получился>
Далее все просто, набираем команду bt и видим стек вызовов функции, далее обычно определить проблему гораздо легче.


И ещё такой момент: при трансляции большинства файлов выскакивает довольно много предупреждений типа:
warning: 'class AAAAA' has virtual functions but non-virtual destructor
Автор уверяет, что это нормально и на это не надо обращать внимания.

Посмотри есть ли наследуемые от этого класса, другие классы.
И вообще сразу сделай этот деструктор виртуальный. И вообще нужно пользоватся правилом :
Или открытый и виртуальный деструктор, либо закрытый и не виртуальный.
We have no beginning, we have no end. We are infinite.
Спасибо сказали:
Аватара пользователя
indie
Сообщения: 87

Re: Программа вылетакет по Segmentation Fault

Сообщение indie »

Не верь автору программы, что все у него работает. Мне тут тоже уверяли, что все работает и замечательно собирается MS VS, а как оказалось помимо синтаксических несаблюдений стандарта, там были и другие "фичи" MS-компилятора.
Кстати, попробуй kdbg (эт морда к gdb, мне очень помогла освоиться с gdb). А также компиль для дебага программу с флагами -g3 -Wall. Еще можно с -fno-stack-protector, помогает найти ошибки, когда программа вываливается с сообщением glibc (stack smashing detected, как-то так).
Спасибо сказали:
MiK13
Сообщения: 1292
ОС: Linux Debian

Re: Программа вылетакет по Segmentation Fault

Сообщение MiK13 »

Спасибо всем, кто помогал решить проблему. Пока её мне решить не удалось, но заставить работать програииу смог.
А проблема почему-то заключена в классе ввода/вывода, т.е. [io]fstream
В программе почти весь ввод/вывод сделан через эти классы и поэтому очень много функций типа

Код: Выделить всё

ifstream& operator>>(ifstream& is, ControlParams& tr) {
  int N = 0;
  is>>N; tr.N1 = N;
   ...
  is>> tr.V;
   ...
  return is;
};

Аналогично и на вывод. Прчём V может быть структурой и для её ввода и вывода определена своя аналогичная функция. И так несколько уровней.
Заставил я програииу работать после того, как заменил

Код: Выделить всё

  try {
    ifstream is( SF );
    if( is.is_open() ) {
      is >> Header;
      is >> ALLParam;
    }
  }
  catch(...) { // Явная проблема  - Файл небыл создан^
  }
на сотню с лишним строк типа

Код: Выделить всё

  FILE *f=fopen(SF,"r");
  if(f) {
    fscanf(f,"%d",&Header);
    printf(" Header = %d\n",Header);
    fscanf(f,"%d %d %d",&ALLParam.Header,&r1,&r2);
    ALLParam.rezerv1 = r1;
    ALLParam.rezerv2 = r2;
     ...
    fclose(f);
  }
  else perror("Error open parameter file");

И тоже самое для вывода (только fprintf вместо fscanf);
После этого программа стала запускаться. Но вылетать при работе. Оказалось, что тоже при выводе через ofstream.
Но это много разных мест и пока я просто в параметрах отключил протоколирование работы. После чего програииа стала работать.
indie писал(а):
24.07.2008 19:15
Не верь автору программы, что все у него работает. Мне тут тоже уверяли, что все работает и замечательно собирается MS VS, а как оказалось помимо синтаксических несаблюдений стандарта, там были и другие "фичи" MS-компилятора.

В наше время верить нельзя никому. Порой даже себе самому ©.
Тут дело не в вере. Я сам видел, как эта же программа, сделаная борландовским билдером в течение весьма длительного времени нормально обрабатывала поступающий поток информации. В то время, как тот же код, перенесённый в Linux и сделанный стандартным gcc нормально работать не захотел.
Другое дело, что его утверждение о соблюдении стандарта языка как-то плохо вяжутся с тем, что после make 2>Err команда wc Err выдаёт
579 5965 63697 Err
Но в ответ на мои замечания по поводу предупреждений он отвечал, что это нормально и подтверждено многолетним опытом. А сам подправить я не могу из-за того, что слишком плохо знаю C++ :(
indie писал(а):
24.07.2008 19:15
Кстати, попробуй kdbg (эт морда к gdb, мне очень помогла освоиться с gdb). А также компиль для дебага программу с флагами -g3 -Wall. Еще можно с -fno-stack-protector, помогает найти ошибки, когда программа вываливается с сообщением glibc (stack smashing detected, как-то так).

-Wall я уже давно стал вставлять в makefile. -g3 попробую. Пока я вставил добавил только -ggdb. С простым -g у меня что-то не понятное. Попробовал поотлаживать программу в Sarge, но gdb почему-то не захотел нормально показывать код. А в Etch с gdb я разобрался довольно быстро. По крайней мере научился устанавливать точки останова, идти по шагам и проверять стек и значения переменных.

А где найти man на gcc?
Т.е. в инете я его нашёл (в виде html-файла), но хотелось бы иметь возможность смотреть его по man gcc.
Спасибо сказали:
yaleks
Сообщения: 2121
Статус: вне статуса
ОС: Gentoo ~

Re: Программа вылетакет по Segmentation Fault

Сообщение yaleks »

Есть ещё компилятор от Intel, ему такое понятие о стандартах тоже не понравится.
Борландовский компилятор для одной архитектуры и для него многие предупреждения действительно могут быть не фатальны. GCC же многоплатформенный компилятор и к тому же более активно используется.
Спасибо сказали: