Я пытаюсь отладить ошибку сегментации программы меню, написанной на «C», и основная функция показана на снимке экрана ниже.
int main( int ac, char **av ) {
/* TDT,II - 02 May 2006 - Added this check to see if there is a Debug level passed in */
if ( ac > 0 ) {
iDebug = atoi( av[1] );
sprintf( cLogText, "Setting Debug Level to ~%d~", iDebug );
WriteTrace( cLogText );
};
initscr();
clear();
t1=time(NULL);
local =localtime(&t1);
Svc_Login();
for ( ; ; ) {
cases_on_pc=FALSE;
if ( !Process_security() ) break;
menu1();
};
wrap_up(0);
endwin( );
exit(0);
}
когда я пытаюсь выполнить отладку (запустить с помощью gdb) без каких-либо аргументов, я останавливаюсь на 0x00007ffff34c323a in ____strtoll_l_internal () from /lib64/libc.so.6
, как показано ниже. if (ac>0)
становится истинным, только когда я передаю какие-либо аргументы. но я не передал никаких аргументов времени выполнения. тем не менее, этот блок 'f выполняется и вызывается функция atoi(av[1])
, что приводит к ошибке сегментации. Я не могу понять это. как действовать дальше, чтобы определить и исправить проблему, чтобы я мог успешно запустить программу меню. может ли кто-нибудь дать какие-либо предложения по этому поводу?
-rw-rw-r--. 1 MaheshRedhat MaheshRedhat 2275270 Jan 10 03:09 caomenu.c
-rw-rw-r--. 1 MaheshRedhat MaheshRedhat 0 Jan 10 03:09 caomenu.lis
-rwxr-xr-x. 1 root root 796104 Jan 10 03:10 scrmenu
[MaheshRedhat@azureRHEL MenuPrograms]$
[MaheshRedhat@azureRHEL MenuPrograms]$ gdb ./scrmenu
(gdb) run
Starting program: /home/MaheshRedhat/MenuPrograms/scrmenu
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff34c323a in ____strtoll_l_internal () from /lib64/libc.so.6
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-189.5.0.1.el8_6.x86_64 libnsl-2.28-189.5.0.1.el8_6.x86_64 ncurses-libs-6.1-9.20180224.el8.x86_64
(gdb)
(gdb) bt
#0 0x00007ffff34c323a in ____strtoll_l_internal () from /lib64/libc.so.6
#1 0x00007ffff34bfce4 in atoi () from /lib64/libc.so.6
#2 0x0000000000401674 in main (ac=1, av=0x7fffffffe228) at caomenu.pc:541
(gdb)
Обновлять
Вышеупомянутая проблема решена. Вот еще одно столкновение с ошибкой сегментации.
из этой трассировки системных вызовов в WriteTrace (cEntryText=0x6f4d20 <cLogText>
в моей основной функции приводит к вызову fputs() из библиотечного файла /lib64/libc.so.6
Starting program: /home/MaheshRedhat/MenuPrograms/scrmenu 1
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff34f7f5c in fputs () from /lib64/libc.so.6
(gdb)
(gdb) bt
#0 0x00007ffff34f7f5c in fputs () from /lib64/libc.so.6
#1 0x0000000000472efc in WriteTrace (cEntryText=0x6f4d20 <cLogText> "Setting Debug Level to ~1~") at caomenu.pc:18394
#2 0x00000000004016a0 in main (ac=2, av=0x7fffffffe208) at caomenu.pc:543
(gdb)
Ниже приведена декларация cLogText
char cLogText[250];
Ниже приведен код для WriteTrace:
/**************************************************************************
routine to write an entry in the trace file
**************************************************************************/
void WriteTrace( char *cEntryText ) {
char cTimeStamp[40]; /* time stamp variable */
char cTimeFormat[] = "%H:%M:%S: "; /* time stamp format */
GetTimeStamp( &cTimeStamp[0], sizeof(cTimeStamp), &cTimeFormat[0] );
TrcFile = fopen( cTraceFile, cTrcOpenFlag ); /* open the file */
cTrcOpenFlag[0] = 'a'; /* after first, always app} */
fprintf(TrcFile, "%s", cTimeStamp); /* write the time stamp */
fprintf(TrcFile, "%s\n", cEntryText); /* write the entry */
fclose(TrcFile); /* close the trace file */
return; /* return to caller */
}
Что такое CtraceFile
? Что такое cTrcopenflag
?
GetTimeStamp( &cTimeStamp[0], sizeof(cTimeStamp), &cTimeFormat[0] );
Это в основном правильно, но редко. Эти массивы уже распадаются на указатели при передаче в функцию. Вместо этого вы можете написать GetTimeStamp( cTimeStamp, sizeof(cTimeStamp), cTimeFormat);
, что более распространено.
if (ac > 0) {
iDebug = atoi(av[1]); // out of bounds here, when you run `./scrmenu`
}
когда вы бежите ./scrmenu
, у вас будут ac=1
и av[0]=./scrmenu
Вы можете неправильно понять ac
и av
значение в функции main
.
как исправить:
if (ac == 2) {
iDebug = atoi(av[1]); // parse the second argument
}
то вы можете запустить: ./scrmenu
или ./scrmenu 1
что-то вроде этого.
вы можете проверить этот пост об аргументе командной строки
спасибо @TiapingHsu. Сейчас работает в этом направлении. Я столкнулся с другой ошибкой сегментации для вызова fputs() из библиотеки. Я обновил свой вопрос. Не могли бы вы проверить один раз
Из С11:
Значение argc должно быть неотрицательным. argv[argc] должен быть нулевым указатель. Если значение argc больше нуля, элементы массива argv[0] по argv[argc-1] включительно должны содержать указатели на строки, которым хост присваивает значения, определенные реализацией среду перед запуском программы. Цель состоит в том, чтобы поставлять информация о программе, определенная до запуска программы из другого места в размещенной среде. Если хост-среда не поддерживает снабжая строки буквами как в верхнем, так и в нижнем регистре, реализация должна гарантировать, что строки будут получены в нижний регистр.
Если значение argc больше нуля, строка указанный argv[0] представляет имя программы; argv[0][0] должен быть нулевой символ, если имя программы недоступно с хоста среда. Если значение argc больше единицы, строки указанный argv[1] через argv[argc-1] представляет программу параметры.
Состояние
( ac > 0 )
было бы истинным, даже если бы вы предоставили 0
аргументы программы, где argv[0]
указывало бы на имя программы (если оно было доступно).
Это утверждение:
atoi( av[1] );
пытается получить доступ к av[1]
, который Стандарт определяет как NULL
, когда аргументы программы не были предоставлены. Отсюда сигнал нарушения сегментации.
fopen
возвращает NULL
, чтобы указать на ошибку.
TrcFile = fopen( cTraceFile, cTrcOpenFlag );
Вы не проверяете его возвращаемое значение здесь, прежде чем передать его в fprintf
.
Возможно:
TrcFile = fopen( cTraceFile, cTrcOpenFlag );
if (!TrcFile) {
deal with error here..
}
спасибо @Haris, теперь это работает в этом аспекте. Я столкнулся с другой ошибкой сегментации для вызова fputs() из библиотеки. Я обновил свой вопрос. Не могли бы вы проверить один раз
В коде, который вы нам предоставили, нет вызова fputs
. Пожалуйста, отредактируйте вопрос, включив в него минимальный воспроизводимый пример, содержащий всю необходимую информацию.
Что такое
WriteTrace
? Что такоеclogText
?