Why is the output of the printf is not show when stepping out the line? But at some point it did print line 16.
c file:
#include<stdio.h>
void nextfunc(){
int ctr;
for(ctr = 0; ctr<3; ctr++){
printf("print ctr = %d",ctr);
}
printf("last print");
}
void main(){
int x;
printf("input x: ");
scanf("%d",&x);
printf("\nprint 2");
printf("\nprint 3");
nextfunc();
}
GDB:
(gdb) break main
Breakpoint 1 at 0x8048479: file file5.c, line 14.
(gdb) break nextfunc
Breakpoint 2 at 0x804843a: file file5.c, line 6.
(gdb) run
Starting program: /home/charmae/workspace/AVT/file5
Breakpoint 1, main () at file5.c:14
14 printf("input x: ");
(gdb) s
15 scanf("%d",&x);
(gdb) s
input x: 4
16 printf("\nprint 2");
(gdb) s
17 printf("\nprint 3");
(gdb) s
print 2
18 nextfunc();
(gdb) s
Breakpoint 2, nextfunc () at file5.c:6
6 for(ctr = 0; ctr<3; ctr++){
(gdb) s
7 printf("print ctr = %d",ctr);
(gdb) s
6 for(ctr = 0; ctr<3; ctr++){
(gdb) s
7 printf("print ctr = %d",ctr);
(gdb) s
6 for(ctr = 0; ctr<3; ctr++){
(gdb) s
7 printf("print ctr = %d",ctr);
(gdb) s
6 for(ctr = 0; ctr<3; ctr++){
(gdb) s
9 printf("last print");
(gdb) s
10 }
(gdb) s
main () at file5.c:19
19 }
(gdb) s
0x0014a113 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6
(gdb) s
Single stepping until exit from function __libc_start_main,
which has no line number information.
print 3print ctr = 0print ctr = 1print ctr = 2last print[Inferior 1 (process 2578) exited with code 012]
Output though stdout is buffered. That means it is saved in a temporary buffer either until the buffer is full, there is a newline being printed or the function fflush(stdout) is called. stdout is flushed automatically also when the program ends.
The reason your output is printed "on the wrong place" in GDB is because of this buffering. you should either add newlines to the end of the printf format string, or explicitly call fflush.
stdio functions like printf are buffered, so it outputs only when it encounters newline.
If you want immediate print use newline character \n or fflush(stdout); after every printf
edit:
Why does printf not flush after the call unless a newline is in the format string?
The trick is that you didn't put in a newline:
printf("last print");
The standard IO library is going to buffer the output until it sees a newline to print. Output to terminals is usually line-buffered; probably gdb runs the program as if it is connected to a terminal, so it prints the previous lines with the \n character in them as they are printed.
The output actually is in the output you've got:
... ctr = 2last print[In ...
The standard IO library flushes all its input streams just before exiting -- via an atexit(3) exit handler -- so the output gets flushed just before the program asks the operating system to tear down its memory and inform its parent that it is dead.
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
So I have been writing a handful of C libraries for my own personal use and I have been doing swell until my latest library, which just contains a bunch of string functions. As you can probably tell by the question title, I am getting a SIGSEGV signal. The problem is this: my research indicates that about 99% of all SIGSEGV errors are due to stack overflow, itself due to bad recursion, but as you will see, I am not using any recursion. Furthermore, there are a few odd problems that occur. For one, printf is exhibiting a lot of funky behavior. GDB encounters printf calls but does not actually seem to execute them until a few lines of code later. Likewise, one of my printf statements is being broken up somehow, and only a part is being called, with another part being chopped off apparently.
Here are the key code snippets, some stuff is named funny because I suspected name clashing may be the cause at one point and may have gone a little overboard...
"firstIndexOf" function (finds the first index of a character in a string, if that character is in said string), found at line 31:
int firstIndexOfFUNCTION(char thisChar, char* inThisString)
{
int lengthABC = strlen(inThisString);
printf("\nLength of %s is %d",inThisString,lengthABC);
int thisFunctionsIndex;
for (thisFunctionsIndex=0;thisFunctionsIndex<lengthABC;thisFunctionsIndex++)
{
printf("\n%dth iteration:\n-char 1 is %c\n-char2 is %c",thisFunctionsIndex,inThisString[thisFunctionsIndex],thisChar);
if (inThisString[thisFunctionsIndex] == thisChar)
{
printf("\nMatch found on iteration %d!",thisFunctionsIndex);
return thisFunctionsIndex;
}
}
printf("\nNo matches detected...");
return -3;
}
The "string_functions_test" function (a function just meant to test the other functions) at line 62:
int string_functions_test()
{
printf("PROGRAM INITIALIZED!\n\n");
char* sft_string;
int sft_index;
sft_string = malloc(sizeof(char)*100);
sft_string = "B um sbm. Sbm B bm.";
printf("2nd BREAKPOINT");
sft_index = firstIndexOfFUNCTION('B',sft_string);
sft_string[sft_index] = 'I';
return 0;
}
and last but not least, good ol' main, at line 107:
int main(int argc, char* argv[])
{
string_functions_test();
return 0;
}
Here is the gdb output for a step-through of my code:
(gdb) b 105
Breakpoint 1 at 0x400970: file string_functions.c, line 105.
(gdb) run
Starting program: /home/user/Development/projects/c/string_functions/source/c/a.out
Breakpoint 1, main (argc=1, argv=0x7fffffffde98) at string_functions.c:109
109 string_functions_test();
(gdb) step
string_functions_test () at string_functions.c:64
64 printf("PROGRAM INITIALIZED!\n\n");
(gdb) next
PROGRAM INITIALIZED!
68 sft_string = malloc(sizeof(char)*100);
(gdb) next
69 sft_string = "B um sbm. Sbm B bm.";
(gdb) next
71 printf("2nd BREAKPOINT");
(gdb) next
73 sft_index = firstIndexOfFUNCTION('B',sft_string);
(gdb) step
firstIndexOfFUNCTION (thisChar=66 'B', inThisString=0x400ab9 "B um sbm. Sbm B bm.") at string_functions.c:33
33 int lengthABC = strlen(inThisString);
(gdb) next
34 printf("\nLength of %s is %d",inThisString,lengthABC);
(gdb) next
2nd BREAKPOINT
36 for (thisFunctionsIndex=0;thisFunctionsIndex<lengthABC;thisFunctionsIndex++)
(gdb) next
38 printf("\n%dth iteration:\n-char 1 is %c\n-char2 is %c",thisFunctionsIndex,inThisString[thisFunctionsIndex],thisChar);
(gdb) next
Length of B um sbm. Sbm B bm. is 19
0th iteration:
-char 1 is B
39 if (inThisString[thisFunctionsIndex] == thisChar)
(gdb) next
41 printf("\nMatch found on iteration %d!",thisFunctionsIndex);
(gdb) next
-char2 is B
42 return thisFunctionsIndex;
(gdb) next
47 }
(gdb) next
string_functions_test () at string_functions.c:75
75 sft_string[sft_index] = 'I';
(gdb) next
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400883 in string_functions_test () at string_functions.c:75
75 sft_string[sft_index] = 'I';
(gdb) next
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
(gdb) quit
You may notice that the printf which prints "2nd Breakpoint" is called, and then the program steps into a different function before the results are seen. I am assuming this is some whacky behavior on the part of the gcc compiler meant to serve as a cpu optimization, but it is sort of messing me up right now obviously. Likewise, the printf in my for loop is being broken up after the first formatted char. These two things are making it super hard to detect what exactly is happening. Has anyone experienced similar behavior?
In case it matters, I am including:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
You are first pointing the pointer sft_string to what is returned from malloc. In the next line you make it point to a literal string. You need to copy it. A literal is built into the source code and cannot be changed during execution. Otherwise it raises a segment fault, which means that an area of memory that has code is being changed. Use strcpy.
In my program, I open a file and write "Hello world" in it. I am using snprintf() to populate 'fname' variable. After this I put gdb on a.out and print the string 'fname'. I see that there are lots of extra character in string 'fname' which I did not assign. Where are these extra characters coming from? Could anyone help please?
3 int main(void)
4 {
5 FILE *debug_fp = NULL;
6 char fname[100];
7
8 snprintf(fname, 100, "./my_debug_%d", getpid());
9 debug_fp = fopen(fname, "w");
10 fprintf(debug_fp, "%s", "Hello world");
11 return 0;
12 }
gdb output:
(gdb) b test.c:10
Breakpoint 1 at 0x4005be: file test.c, line 10.
Breakpoint 1, main () at test.c:10
10 fprintf(debug_fp, "%s", "Hello world");
(gdb) p fname
$1 = "./my_debug_16178\000\000\000\000\000\000\000\000\300\313Ab:\000\000\000\360\005#\000\000\000\000\000\063\004#\000\000\000\000\000\001\000\000\000\000\000\301\000'\006#", '\000' <repeats 13 times>"\300, \313Ab:\000\000\000\360\005#", '\000' <repeats 13 times>"\260, \343\377\377"
(gdb) q
Thank you.
In this case gdb doesn't care about your 0-terminator in the string and just prints the array, i.e. the full 100 characters in fname.
You can also use printf "%s" or p /s if you want gdb to treat your array as a C-string.
As your question is about seeing a lot of extra characters that you didnt assign, it is always the best practice to initialize the memory (simple variables, arrays or pointers) you define, so that you always see what you expect.
In your case, you could do:
char fname[100] = {0};
The response I get from gdb is more predictable thus:
(gdb) b 9
Breakpoint 1 at 0x400610: file st_fname.c, line 9.
(gdb) run
Starting program: /home/gops/data/samples/st_fname.o
Breakpoint 1, main () at st_fname.c:9
9 fprintf(debug_fp, "%s", "Hello world");
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.7.x86_64
(gdb) p fname
$1 = "./my_debug_26808", '\000' <repeats 83 times>
(gdb)
Now you should see what you expect. Hope it helps.
I'm experimenting with python-interactive mode in gdb, and I can't figure out how to change a variable from inside it. I know how to do it without python - set variable a = 10.
I'm using this test program:
#include <stdio.h>
int main(int argc, char *argv) {
int a;
printf("Enter a: ");
scanf("%d", &a);
printf("You entered: %d\n", a);
}
I've placed a breakpoint after the scanf(), and when it's hit I enter python interactive mode. Now I want to change the variable a to some other value. I tried using a = 10, but it wasn't changed, and the same value I entered in the scanf() (in this case it's 5) was printed instead.
(gdb) b main.c:6
Breakpoint 1 at 0x8048503: file main.c, line 6.
(gdb) r
Starting program: /home/sashoalm/Desktop/test/a.out
Enter a: 5
Breakpoint 1, main (argc=1, argv=0xbffff1d4 "\214\363\377\277") at main.c:6
6 printf("You entered: %d\n", a);
(gdb) python-interactive
>>> a = 10
>>>
(gdb) c
Continuing.
You entered: 5
[Inferior 1 (process 26133) exited normally]
So what is the correct way to do it?
After some searching through the Python API documentation I found the answer. I needed to use gdb.execute('set var a = 10'), which allows python scripts to execute gdb commands, and the commands are evaluated as if the user has written them.
I used this code to read a, add 5 to it and then set it:
symbol = gdb.lookup_symbol('a')[0]
frame = gdb.selected_frame()
value = symbol.value(frame)
gdb.execute('set var a = %d' % (int(value)+5))
I'm currently printing the contents of a variable from gdb like this:
(gdb) call printf("%s",buffer)
The buffer contains a large string and I want to redirect it to a file rather than screen.
Enabling logging feature in gdb will not help here. And I'm not able to use > command to redirect either. Ofcourse I can create a file in the program and write the buffer to this file and invoke the write to file through gdb. But is there a easier way out?
This will redirect the target's stdout to a file of your choice, call printf, then restore stdout to its previous setting. fflush is called right before changing the file descriptor, so that output gets sent to the correct place.
$ gdb f
...
(gdb) list
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 main()
6 {
7 char buf[] = "test";
8
9 printf("%p ", (void *)buf);
10 printf("%d\n", strlen(buf));
11 }
(gdb) break 10
Breakpoint 1 at 0x80484d3: file f.c, line 10.
(gdb) run
Starting program: f
Breakpoint 1, main () at f.c:10
10 printf("%d\n", strlen(buf));
(gdb) call fflush(stdout)
0xbffff117 $1 = 0
(gdb) call dup(1)
$2 = 3
(gdb) call creat("/tmp/outputfile",0644)
$3 = 4
(gdb) call dup2(4,1)
$4 = 1
(gdb) call printf("%s\n", buf)
$5 = 5
(gdb) call fflush(stdout)
$6 = 0
(gdb) call dup2(3,1)
$7 = 1
(gdb) call close(3)
$8 = 0
(gdb) call close(4)
$9 = 0
(gdb) cont
Continuing.
4
[Inferior 1 (process 3214) exited with code 02]
(gdb) shell cat /tmp/outputfile
test
You aren't able to use > or you did not know how to use it in gdb? You can redirect output from inside of gdb. Try:
(gdb) run > out.txt
(gdb) run > /dev/null