I am trying to debug the segmentation fault of a menu program written in 'C' and the main function is shown in the below screen shot.
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);
}
when i try to debug (run using gdb), without any arguments, getting halted at 0x00007ffff34c323a in ____strtoll_l_internal () from /lib64/libc.so.6 as shown below. if(ac>0) becomes true, only when i pass any arguments. but i haven't passed any runtime arguments. still that 'f block is being executed and function atoi(av[1]) is called and resulted in segmentation fault. I am unable to figure it out. how to proceed further to identify and correct the issue so that i could run the menu program successfully. could somebody give any suggestions on this?
-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)
Update
The above issue has been resolved. Here is another encounter of segmentation fault.
from this backtrace of system calls, in WriteTrace (cEntryText=0x6f4d20 <cLogText> in my main function lead to call fputs() from library file /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)
The below is the declaration of cLogText
char cLogText[250];
The below is code for 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 */
}
From C11:
The value of argc shall be nonnegative. argv[argc] shall be a null
pointer. If the value of argc is greater than zero, the array members
argv[0] through argv[argc-1] inclusive shall contain pointers to
strings, which are given implementation-defined values by the host
environment prior to program startup. The intent is to supply to the
program information determined prior to program startup from elsewhere
in the hosted environment. If the host environment is not capable of
supplying strings with letters in both uppercase and lowercase, the
implementation shall ensure that the strings are received in
lowercase.
If the value of argc is greater than zero, the string
pointed to by argv[0] represents the program name; argv[0][0] shall be
the null character if the program name is not available from the host
environment. If the value of argc is greater than one, the strings
pointed to by argv[1] through argv[argc-1] represent the program
parameters.
The condition
( ac > 0 )
would be true even if you provided 0 program arguments, with argv[0] pointing to the program name (if it was available).
This statement:
atoi( av[1] );
tries to access av[1] which the Standard defines to be NULL when no program arguments were provided. Hence the segmentation violation signal.
fopen returns NULL to indicate failure.
TrcFile = fopen( cTraceFile, cTrcOpenFlag );
You do not check its return value here, before passing it to fprintf.
Perhaps:
TrcFile = fopen( cTraceFile, cTrcOpenFlag );
if (!TrcFile) {
deal with error here..
}
if (ac > 0) {
iDebug = atoi(av[1]); // out of bounds here, when you run `./scrmenu`
}
when you run ./scrmenu, you will have ac=1 and av[0]=./scrmenu
You may misunderstand ac and av mean in the main function.
how to fix:
if (ac == 2) {
iDebug = atoi(av[1]); // parse the second argument
}
then you can run: ./scrmenu or ./scrmenu 1 something like this.
you can check this post about command line argument
Related
I have this simple script written in C:
#include <stdio.h>
void usage(char *program_name) {
printf("Usage: %s <message> <# of times to repeat>\n", program_name);
exit(1);
}
int main(int argc, char *argv[]) {
int i, count;
// if(argc < 3) // If less than 3 arguments are used,
// usage(argv[0]); // display usage message and exit.
count = atoi(argv[2]); // convert the 2nd arg into an integer
printf("Repeating %d times..\n", count);
for(i=0; i < count; i++)
printf("%3d - %s\n", i, argv[1]); // print the 1st arg
}
And I'm making some test with GDB.
I did this:
(gdb) run test
Starting program: /home/user/Desktop/booksrc/convert2 test
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
Obviusly it goes in segmentation fault because to work the program needs three argv. And I commented the lines that do the control. So it goes in error.
(gdb) where
#0 0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
#1 0x00007ffff7a53a80 in atoi () from /usr/lib/libc.so.6
#2 0x00005555555546ea in main (argc=2, argv=0x7fffffffe958) at convert2.c:14
(gdb) break main
Breakpoint 1 at 0x5555555546d2: file convert2.c, line 14.
(gdb) run test
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/user/Desktop/booksrc/convert2 test
Breakpoint 1, main (argc=2, argv=0x7fffffffe958) at convert2.c:14
14 count = atoi(argv[2]); // convert the 2nd arg into an integer
(gdb) cont
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a56e56 in ____strtoll_l_internal () from /usr/lib/libc.so.6
(gdb) x/3xw 0x7fffffffe958 // this is memory of the "argv" some line before
0x7fffffffe958: 0xffffebfe 0x00007fff 0xffffec22
(gdb) x/s 0xffffebfe
0xffffebfe: <error: Cannot access memory at address 0xffffebfe>
(gdb) x/s 0x00007fff
0x7fff: <error: Cannot access memory at address 0x7fff>
(gdb) x/s 0xffffec22
0xffffec22: <error: Cannot access memory at address 0xffffec22>
In theory, with "x/s" I should have seen the commandline in the first address and "test" in the second address and the null in the third. But nothing. If I copy paste that address to a ascii to string converter, it gives me data without any sense. What am I doing wrong?
Your platform uses 64bit pointers, so try :
(gdb) x/3xg 0x7fffffffe958
to display the 64bit pointers in the argv array, and then :
(gdb) x/s 0x00007fffffffebfe
or just :
(gdb) p argv[0]
First of all always check if the command line is correct
Uncomment the check from your code.
Then in the gdb set the arguments (before running it)
(gdb) set args "hello world" 12
printf() throws a segmentation fault when I pass a null-terminated string for some reason.
Here's a demonstration of my problem in GDB
λ sudo gdb -q notesearch
Reading symbols from notesearch...done.
(gdb) break 53
Breakpoint 1 at 0x400b32: file notesearch.c, line 53.
(gdb) run
Starting program: /home/frosty/hack/chapter_2/code/notesearch
[DEBUG] UserID: 0
[DEBUG] File Descriptor: 3
Breakpoint 1, print_notes (fd=3, uid=0, searchstring=0x7fff3daf7fc0 "")
at notesearch.c:53
53 printf("%s\n", note_buffer);
(gdb) x/8xb note_buffer
0x7feb5a997168: 0x68 0x65 0x6c 0x6c 0x6f 0x0a 0x00 0x00
(gdb) x/s note_buffer
0x7feb5a997168: "hello\n"
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
_dl_fixup (l=, reloc_arg=)
at ../elf/dl-runtime.c:148
148 ../elf/dl-runtime.c: No such file or directory.
(gdb)
Here's the source code around the problem
int print_notes(int fd, int uid, char *searchstring){
int note_length = find_user_note(fd, uid);
if (note_length == -1)
return 0; // End of file
char* note_buffer;
read(fd, note_buffer, note_length);
note_buffer[note_length] = 0; // null terminator byte
if(search_note(note_buffer, searchstring)) {
printf("%s\n", note_buffer);
}
return 1;
}
remember that in C, arrays are indexed from 0 through (length of array-1)
This line:
char* note_buffer;
declares an initialized pointer to character. I.E. its value depends on what ever trash is currently in memory at that location. Such an action as accessing where that trash 'points' would be undefined behavior and can lead to a seg fault event.
Strongly suggest, after this line:
char* note_buffer;
inserting the following: (including the checking for a malloc() failure:
note_buffer = malloc( note_length+1 );
if( !note_buffer )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
Note: without the +1 on the call to malloc() the following line:
note_buffer[note_length] = 0;
would be setting a byte that is one past the end of the allocated area. That would be undefined behavior and can lead to a seg fault event
Also, a 0 has the bit pattern 0x000000000000000000000000 and a '\0' has the bit pattern 0x00000000. the implicit conversion feature will save you in this instance, but do not rely on that feature, instead properly code literals. so the line should be:
note_buffer[note_length] = '\0';
Note: perror() outputs the enclosed text string AND the reason the OS thinks the error occurred to stderr, which is where all error messages should be output.
Null terminator is indicated by \0 not 0
note_buffer[note_length] = 0;
should be
note_buffer[note_length] = '\0';
I'm relatively new to C and I have a problem with the following:
regex_t re;
regmatch_t matches[2];
int start;
int end;
int count = 0;
int reti = regcomp(&re, "^(?:[a-zA-Z]|[a-zA-Z](?:[a-zA-Z0-9\\-])*[a-zA-Z0-9])(?:\\.(?:[a-zA-Z]|[a-zA-Z](?:[a-zA-Z0-9\\-])*[a-zA-Z0-9]))*$", REG_EXTENDED);
while (1) {
printf("Local = %s\n", local);
reti = regexec(&re, local, 2, matches, 0);
// More code here
}
When I run this, I get a segmentation fault.
local was defined as char *local and is being printed out correctly.
I ran the code using GDB and it turns out the issue is arising at the line:
reti = regexec(&re, local, 2, matches, 0);
I can't seem to figure out why.
This is the output from gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7af8d42 in regexec () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) backtrace
#0 0x00007ffff7af8d42 in regexec () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x000000000040092d in email_in (str=0x400aa8 "giri#gmail.com") attestdriver.c:70
#2 0x0000000000400780 in main () at testdriver.c:15
Would anyone have any ideas as to what might be the issue?
Thanks for your help.
The problem is actually here:
int reti = regcomp(&re, "^(?:[a............
From here:
You need to check the return of regcomp, it will tell you that your regex is invalid.
You will get Invalid preceding regular expression
(?: is not supported by POSIX regexes.
It's throwing this error because:
A common way to get a segfault is to dereference a null pointer
(From here)
The regex cannot initialize because of the illegal (?:
The original error is shown in the return of regcomp, and does not halt execution.
I am asked to put a random seeding into a program that is called when a user types in -r. It is shown to look like
-r1234567
So as a global variable I set Random = 1234567.
I added this to the top of my function as well:
printf("Seed: %d\n", Random);
srand48(Random);
Every time I use -r1234567 My program segfaults and says this:
Program received signal SIGSEGV, Segmentation fault.
____strtol_l_internal (nptr=0x0, endptr=0x0, base=10, group=<optimized out>,
loc=0x7ffff7ad8020) at ../stdlib/strtol_l.c:298
298 ../stdlib/strtol_l.c: No such file or directory.
(gdb) bt
#0 ____strtol_l_internal (nptr=0x0, endptr=0x0, base=10, group=<optimized out>,
loc=0x7ffff7ad8020) at ../stdlib/strtol_l.c:298
#1 0x00007ffff77589e0 in atoi (nptr=<optimized out>) at atoi.c:28
#2 0x0000000000401d8c in getCommandLine (argc=6, argv=0x7fffffffe238)
at prog.c:171
#3 0x0000000000401514 in main (argc=6, argv=0x7fffffffe238) at prog.c:35
(gdb) up
#1 0x00007ffff77589e0 in atoi (nptr=<optimized out>) at atoi.c:28
28 atoi.c: No such file or directory.
(gdb) up
#2 0x0000000000401d8c in getCommandLine (argc=6, argv=0x7fffffffe238)
at prog.c:171
warning: Source file is more recent than executable.
In my command like: the case looks like this:
while ((c = getopt(argc, argv, "g:n:a:h:s:d:v:r")) != -1)
case 'r': Random = atoi(optarg); break;
So a user wants to to randomize using a seed. They do ./program -r1234567. This then goes into the two lines of code that I put above and should randomize.
Any suggestions?
Your problem is the getopt call, in that you forgot to tell getopt that the -r argument takes a value:
getopt(argc, argv, "g:n:a:h:s:d:v:r:")
/* ^ */
/* | */
/* Add colon here */
Because of that, the optarg pointer is NULL when you call atoi.
you are giving -r1234567 from the command line , How you are parsing it and giving ito atoi ?
if atoi get "1234567" as its argument then there should not be any problem .. Can you paste the logic which parses the argv[1] ?
Are declaring Random as an int?. srand48 takes a long as an argument so you should be usuing atol instead of atoi:
long Random = 42;
printf("Seed: %d\n", Random);
srand48(Random);
The problem is .. you are missing ":" at the end of argument r ...because of this NULL is being passed to atoi .. try adding ":" at the end of r in the getopt !!
I'm making this little program that just reads contents of a file, but when I run it I get this error: Program received signal: “EXC_BAD_ACCESS”.
I also get a warning from Xcode: "Assignment makes pointer from integer without a cast" at line 10 of my code (main.c):
#include <stdio.h>
#include <stdlib.h>
#define FILE_LOCATION "../../Data"
int main (int argc, const char * argv[]) {
FILE *dataFile;
char c;
if ( dataFile = fopen(FILE_LOCATION, "r") == NULL ) {
printf("FAILURE!");
exit(1);
}
while ( (c = fgetc(dataFile)) != EOF ) {
printf("%c", c);
}
fclose(dataFile);
return 0;
}
This is the debugger output:
[Session started at 2012-06-27 10:28:13 +0200.]
GNU gdb 6.3.50-20050815 (Apple version gdb-1515) (Sat Jan 15 08:33:48 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys000
Loading program into debugger…
Program loaded.
run
[Switching to process 34331]
Running…
Program received signal: “EXC_BAD_ACCESS”.
sharedlibrary apply-load-rules all
(gdb)
Is there a problem with the pointer, wrong function? I found something to track memory issues wich is called NSZombie, what is that and can I use it?
if ( (dataFile = fopen(FILE_LOCATION, "r")) == NULL ) {
Here's another error:
char c;
while ( (c = fgetc(dataFile)) != EOF ) {
You should really study the documentation for important functions like fgetc() before using them.
Specifically, fgetc() returns int, which is required in order to fit the EOF value. If it returned char, then there would have to be one character whose numerical value collided with EOF and that, thus, couldn't appear in a binary file. That would suck, so that's not how it works. :)