Как избавится от ошибки?

Все о программировании под *nix
Max

Как избавится от ошибки?

Сообщение Max »

Начал делать курсач в коммандной строке, используя для графики ncurses.
Меня задолбала ошибка Segmentation fault :x
При компиляции никаких ошибок нет.
Притом что самое досадное, теперь когда я убрал фрагмент кода, вызывающий ошибку, старая часть программы, работающая до этого нормально, тоже вызывает ее.
Не знаю что делать?
Заново не хочется писать, причем если и напишу, то примерно тоже самое, вдруг опять тоже самое будет?
Не знаю что делать, может кто подскажет что-нибудь?

Аватара пользователя
Llama
Неотъемлемая часть форума
Сообщения: 9749
Зарегистрирован: 06 фев 2002, 11:40
Откуда: Менск

Сообщение Llama »

Max, я что шаман и должен догадаться?
Давай код сюда.

Как вариант - использование printf/scanf до endwin или другое вмешательство в работу ncurses. Если время поджимает - звони 4001738 - посмотрим вместе - я буду в первом копусе сегодня-завтра.
Опыт растет прямо пропорционально выведенному из строя оборудованию

Аватара пользователя
exe
Неотъемлемая часть форума
Сообщения: 860
Зарегистрирован: 28 ноя 2003, 21:08
Откуда: Минск

Сообщение exe »

Max,

Используй valgrind или memprof.

Аватара пользователя
fa3a
Неотъемлемая часть форума
Сообщения: 619
Зарегистрирован: 25 июл 2003, 17:22
Откуда: Minsk

Сообщение fa3a »

используй strace для отслеживания системных call-ов... а так же gdb с ddd...
Never touch the running program!!!

Max

Сообщение Max »

Используй valgrind или memprof.
Может кто объяснит что это такое.
Код завтра выложу, дома инета нет.
P.S.
Кстати кто-нибудь знает какой-нибудь стандартный отладчик,
а то компилирую я g++ file. А отладчика не знаю, без него совсем плохо... :(

Anklav
Заглянувший
Сообщения: 11
Зарегистрирован: 26 апр 2004, 16:03
Откуда: Минск
Контактная информация:

Сообщение Anklav »

Кстати кто-нибудь знает какой-нибудь стандартный отладчик,
Ну так gdb и есть "стандартный отладчик"

Аватара пользователя
fa3a
Неотъемлемая часть форума
Сообщения: 619
Зарегистрирован: 25 июл 2003, 17:22
Откуда: Minsk

Сообщение fa3a »

ddd -- нрафическая оболочка для gdb.. очень рекомендую.. :-)
Never touch the running program!!!

Аватара пользователя
exe
Неотъемлемая часть форума
Сообщения: 860
Зарегистрирован: 28 ноя 2003, 21:08
Откуда: Минск

Сообщение exe »

memprof и valgrind используются для проверки программ
на неправильное обращение с памятью. Довольно лёгкие
в использовании.

Гость

Сообщение Гость »

segmentation fault генерирует core dump. Загрузи его в gdb, посмотри стек вызовов функций (команда bt в gdb) - и сразу найдешь ту строку в коде где твоя проблема.
тебе нужно сделать что-то вроде этого:
1. g++ -g 1.cpp
2. ulimit -c unlimited
3. ./a.out
Segmentation fault (core dumped)
4. gdb a.out core.xxx
(gdb) bt
#0 0x4018514c in memcpy () from /lib/libc.so.6
#1 0x08048399 in main (argc=134513528, argv=0x1) at 1.cpp:5
#2 0x4011e917 in __libc_start_main () from /lib/libc.so.6

проблема - файл 1.cpp строка 5.

Аватара пользователя
exe
Неотъемлемая часть форума
Сообщения: 860
Зарегистрирован: 28 ноя 2003, 21:08
Откуда: Минск

Сообщение exe »

Anonymous писал(а):segmentation fault генерирует core dump. Загрузи его в gdb, посмотри стек вызовов функций (команда bt в gdb) - и сразу найдешь ту строку в коде где твоя проблема.
Проблема почти всегда в другом месте. gdb показывает где она
проявилась. А вот чтобы найти место её возникновения, т.е.
почему она вообще есть, используются

memprof, valgrind, ZeroFault, Purify, WorkShop Performance Analyzer
и куча других продуктов.

Гость

Сообщение Гость »

Если есть "устойчивый" core dump - т.е. программа падает все время в одной и той же точке - в большинстве случаев проблему можно быстро отследить в gdb - анализируя стек.
Да и в других случаях если есть core dump - я всегда для начала загружаю его в gdb и смотрю в какой точке произошел сбой прежде чем переходить к вышеперечисленным средствам (которые тоже не факт что помогут).

Max

Сообщение Max »

Вот исходный текст:

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

#include <ncurses/curses.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <link.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include <gnu/libc-version.h>
#include <memory.h>
//*************My Fynctions*****************//
char* ComputerInform(void);
char* SoftInform(void);
char* PaswInform(void);
char* FileSysInform(void);
char* ReadFileInfo(char* path,char* param);
//************Globals**********************//
static char OSVerPath[]="/etc/issue";
static char IPPath[]="/etc/hosts";
static char NWPath[]="/etc/sysconfig/network";
static char NWExPath[]="/etc/sysconfig/networking/ifcfg-lo";
static char PSWPath[]="/etc/login.defs";
static char FSysPath[]="/etc/fstab";
  
static char compinf[100];
static char softinf[100];
static char fileret[1000];
static char paswinf[100];
static char fsysinf[100];

//************Main Module**************//
static void finish(int sig);
int Menu; 
static char* MenuStr[10] = {"Система","Версия ПО","Тип входа","Политика паролей","Файловая система","TCP/IP","Сервисы","Аудит","DDoS","Выход (ESC)"};
 static int com;
int main(){
    /* инициализируй свои не относящиеся к curses структуры данных здесь */
Menu = 0;
  
    (void) signal(SIGINT, finish);      /* подготовить прерывания для завершения */

    (void) initscr();      /* инициализировать библиотеку curses */
    keypad(stdscr, TRUE);  /* разрешить преобразование кодов клавиатуры */
    (void) nonl();         /* не делать NL->CR/NL при выводе */
    (void) cbreak();       /* читать один символ за раз, не ждать \n */
    (void) noecho();       /* не показывать ввод */
    if (has_colors())
    {
        start_color();

        /*
         * Простое назначение цветов, часто нужное всем.
         */
        init_pair(1, COLOR_GREEN, COLOR_BLACK);
        init_pair(2, COLOR_MAGENTA, COLOR_BLACK);
      }

    while(1){
        move(0,0);
       	int x = 0,y = 0,tx=0,ty=0; 
	if(com==27) break;
	switch(com){
	case 260:{
	if(Menu>0) Menu--;
	break;
	}
	case 261:{
        if(Menu<9) Menu++;
	break;
	}
	case 13:{
	clear();
	move(0,0);
	switch(Menu){
	case 0:{
	printw("Информация о системе:\n",ComputerInform());
	getch();
	break;
	}
	
	
	
	
	
	
	
	
	}
	break;
	}}
        color_set(1,NULL);
	//*****draw menu*****///
	for(int i = 0;i<10;i++){
	if(Menu ==i){
	 getyx(stdscr,x,y);
	 }
	printw("%s",MenuStr[i]);
	getyx(stdscr,tx,ty);
	move(tx,ty+1);
	}
	move(x,y);
	color_set(2,NULL);
	printw("%s",MenuStr[Menu]);
        com = getch();
	clear();
    }

    finish(0);
    return 1;               /* мы закончили */
}

static void finish(int sig)
{
    endwin();

}
char* ComputerInform()
{
  FILE *f;
  struct utsname uname_info;
  char  tmp[256];
  bool ip=false,nw=false;

  if(uname(& uname_info) == -1)
  {
     strcat(compinf,"Ошибка при получении информации");
  }
  strcat(compinf,"Тип операционной системы:\t ");
  strcat(compinf,uname_info.sysname);
  if((f = fopen(OSVerPath,"rt"))!=NULL){
  strcat(compinf,"\nВерсия операционной системы:\t ");
  fgets(tmp,256,f);
  strcat(compinf,tmp);
  memset(tmp,sizeof(tmp),0);
  fclose(f);
  }
  strcat(compinf,"\nПоддержка сети:\t ");
//Здесь вызывается функция и идет ошибка       if((strstr(ReadFileInfo(NWPath,"NETWORKING"),"YES")!=NULL)||(strstr(ReadFileInfo(NWPath,"NETWORKING"),"yes")!=NULL)){
  strcat(compinf,"да ");
  nw = true;
  }else{
  strcat(compinf,"нет ");
  }
  strcat(compinf,"\nИмя хоста:\t ");
  strcat(compinf,uname_info.nodename);
  if((f = fopen(IPPath,"rt"))!=NULL){
  strcat(compinf,"\nIP адрес:\t ");
  fgets(tmp,256,f);
  for(int i = 0;i<256;i++){
  if(tmp[i]==9){
  tmp[i]='\0';
  break;
  }
  }
  strcat(compinf,&tmp[0]);
  memset(tmp,sizeof(tmp),0);
  fclose(f);
  }
  if(strstr(compinf,"127.0.0.1")==NULL) ip = true;
  strcat(compinf,"\nДомен:\t ");
  strcat(compinf,uname_info.domainname);
  strcat(compinf,"\nРоль:\t ");
  if(nw&&(strstr(uname_info.domainname,"none")!=NULL)) strcat(compinf,"Станция в локальной сети\n");
  if(nw&&ip&&(strstr(uname_info.domainname,"none")==NULL)) strcat(compinf,"Контроллер домена\n");
  if(!nw) strcat(compinf,"Выделенная станция\n");
      return &compinf[0];
}
char* ReadFileInfo(char* path,char* param){
FILE *f;
char  buf[256];
char* pParam;
bool beg = false;
char tmp[2] = {0,0};
memset(fileret,sizeof(fileret),0);
if((f = fopen(path,"rt"))==NULL) return "Ошибка чтения файла";
while(!feof(f)){
fgets(buf,256,f);
if(buf[0]=='#') continue;
if((pParam=strstr(buf,param))!=NULL){
int i,k = 0;
while(1){
i++;
tmp[0]= *(pParam+strlen(param)+i-1);
if((!beg)&&((tmp[0]=='\t')||(tmp[0]=='=')||(tmp[0]==' '))) continue;
beg = true;
fileret[k] = *(pParam+strlen(param)+i-1);
k++;
if((tmp[0]=='\n')||(tmp[0]=='\r')) break;
}
fileret[strlen(fileret)-1]='\0';
break;
}
}
fclose(f);
return &fileret[0]; 
}
char* SoftInform(){
struct utsname uname_info;
  if(uname(& uname_info) == -1)
  {
     strcat(compinf,"Ошибка при получении информации");
  }
strcat(softinf,"Версия ядро: \t ");
strcat(softinf,uname_info.release);
strcat(softinf,"\nДата релиза:\t ");
strcat(softinf,uname_info.version);
return &softinf[0];
}
char* PaswInform(void){
/*strcat(paswinf,"\n:Максимальное колличество дней использования пароля \t");
strcat(paswinf,pmaxd);
strcat(paswinf,"\n:Минимальное колличество дней между сменой пароля \t");
strcat(paswinf,pmind);
strcat(paswinf,"\n:Минимально допустимая длинна пароля \t");
strcat(paswinf,pminl);
strcat(paswinf,"\n:Количество дней, после которого подается сообщение об устаревании пароля \t");
strcat(paswinf,pmes);
strcat(paswinf,"\n");*/
return &paswinf[0];
}
char* FileSysInform(void){
/*strcat(fsysinf,"\n:Тип файловой системы \t");
strcat(fsysinf,ReadFileInfo(FSysPath,"PASS_MAX_DAYS"));
strcat(fsysinf,"\n:Точка монтирования \t");
strcat(fsysinf,ReadFileInfo(FSysPath,"PASS_MIN_DAYS"));
strcat(fsysinf,"\n:Тип корневой фаловой системы \t");
strcat(fsysinf,ReadFileInfo(FSysPath,"PASS_MIN_LEN"));*/
return &fsysinf[0];
}

Посмотрите может кто-чего увидит или подскажет как сделать лучше!!

Аватара пользователя
exe
Неотъемлемая часть форума
Сообщения: 860
Зарегистрирован: 28 ноя 2003, 21:08
Откуда: Минск

Сообщение exe »

Max,

Ты конечно извини, но этот код похож на пример как не надо
программировать. Обрати внимание на статические массивы,
где размеры указаны цифрами. Ну неужели нету констант в
системных include файлах? Если нету сам сделай -
но только правильно.

passwinf[100] - ты в него загоняешь strcat-ом сколько данных?
fsysinf - то же самое.
Размеры надо учитывать!

Ты же разрушил всю статику, и прога у тебя должна coredump делать.

Max

Сообщение Max »

Ты же разрушил всю статику, и прога у тебя должна coredump делать.
Не мог бы пояснить.
Раньше я делал их все char* но постоянно была ошибка Segmentation fault.
Причем сейчас ошибки в основном бывают из-за функции ReadFileInfo(Path,Parametr);
Она исчет в системных файлах параметры и возвращает значения.
Причем самое странное, когда ее вызываешь из main то она все делает правильно, а когда из моих функций, или ерунду или Segmentation fault.
Почему????

Аватара пользователя
exe
Неотъемлемая часть форума
Сообщения: 860
Зарегистрирован: 28 ноя 2003, 21:08
Откуда: Минск

Сообщение exe »

Max,

Когда ты пишешь 200 байт в 100 байтный массив, то
перезаписывается что-то другое, которое находится
после этого массива в памяти. Я же не компилятор, не знаю
точно что там находится. Такое обязательно приведет
к coredump, вопрос только когда и где. Оно может даже
работать правильно. Это называется Undefined behaviour.

Для начала замени все 100 на 10000, хотя это и не правильно.

Если не знаешь сколько места понадобится, то получай память
динамически, когда это узнаешь (malloc,calloc,free).
alloca тоже ничего если переносимость не надо и стэка не жаль.

Указатели, это главное достоинство и главная проблема C.

Ответить