printf segment error (core dump): a problem caused by formatted output

Posted by anthill on Mon, 28 Feb 2022 02:45:27 +0100

1. printf segment error (core dump): a problem caused by formatted output

Post a simple example:

#include <stdio.h>

int main(){
    int len = sizeof(int);
    printf("%s\n",len);
    return 0;
}

`root@ubuntu:test#gcc test.c
test.c: In function 'main':
test.c:5:2: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat=]
printf("%s\n",len);
^`
`
root@ubuntu:test# ./a.out
Segmentation fault (core dumped)
`

Because the project file is relatively large, I didn't pay attention to some important compilation warnings when compiling with Makefile, and I also upgraded the version. It took two or three days to find that it was really printf that caused my own program segment error after debugging with gdb.
Post the gdb running error of the project: the thread named CoreThread receives a signal segment error

(gdb) bt
Thread 12 "CoreThread" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffed7fa700 (LWP 21396)]
0x00007ffff6d95cd0 in _IO_vfprintf_internal (s=0x7ffff710c620 <_IO_2_1_stdout_>, 
    format=<optimized out>, ap=ap@entry=0x7fffed7f9cf8) at vfprintf.c:1632
1632    vfprintf.c: No such file or directory.

2, use the gdb "bt" command to display the current call stack.

(gdb) bt
#0  0x00007ffff6d95cd0 in _IO_vfprintf_internal (s=0x7ffff710c620 <_IO_2_1_stdout_>, 
    format=<optimized out>, ap=ap@entry=0x7fffed7f9cf8) at vfprintf.c:1632
#1  0x00007ffff6e5daef in ___printf_chk (flag=1, format=<optimized out>)
    at printf_chk.c:35
#2  0x000000000041f10c in printf (
    __fmt=0x5b3bc0 "%s, startPushStream success, channel: %d, session_id:%s;lv_stream_type_e:%d, bastime:  %d, offset:  %d, worktype: %d\n")
    at /usr/include/x86_64-linux-gnu/bits/stdio2.h:104
#3  StartPushStream (channelId=channelId@entry=0, session=session@entry=0x7fffed7f9ea0, 
    type=type@entry=SDK_LV_STREAM_CMD_LIVE) at nvr_demo/nvrCallback.cpp:235
#4  0x000000000042004c in NvrStartPushStreamingCb (channelId=0, 
    session=0x7fffed7f9ea0, param=0x7fffd400be20) at nvr_demo/nvrCallback.cpp:584
#5  0x0000000000417140 in StartNvrPushStreamingCb (auth=0x1407f80, param=0x7fffd400be20)
    at ../src/core_cb/cb_to_cloud.c:885
#6  0x0000000000462619 in linkvisual::JobPool::jobProcess(void*) ()
#7  0x00007ffff71186ba in start_thread (arg=0x7fffed7fa700) at pthread_create.c:333
#8  0x00007ffff6e4e51d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 

3. Find the cause of the error

According to the current call stack information of gdb, we positioned the #2 to find the printf in the startPushStream function, and found the new version of session_. The type of ID is int, but% s is used for printing here, resulting in a segment error due to the old version of session_ The ID type is char *, so there is no error.

When there is a segment error in your program, the flexible use of gdb can speed up the speed of locating the error and save time, rather than adding printing, which is a cumbersome debugging and locating method.

4. Some common methods of gdb are

1. Run command

Run: abbreviated as r, its function is to run the program. When a breakpoint is encountered, the program will stop running at the breakpoint and wait for the user to enter the next command.
Continue (abbreviated as c): continue execution to the next breakpoint (or end of operation)
Next: (abbreviated as n), a one-step tracking program that does not enter the function body when a function call is encountered; The main difference between this command and step is that when step encounters a user-defined function, it will step into the function to run, while next will directly call the function and will not enter the function body.
Step (abbreviated as s): single step debugging. If there is a function call, enter the function; Unlike the command n, n does not enter the called function
Until: when you are tired of stepping in a loop, this command can run the program until you exit the loop.
until + line number: run to a line, not just to jump out of the loop
finish: run the program until the current function returns, and print the stack address, return value, parameter value and other information when the function returns.
Call function (parameter): call the function visible in the program and pass "parameter", such as call gdb_test(55)
quit: abbreviated as q, exit gdb

2. Set breakpoint

break n: set the breakpoint at line n
(you can bring the code path and code name: b OAGUPDATE.cpp:578)
b fn1 if a > b: conditional breakpoint setting
break func (abbreviated as b): set a breakpoint at the entrance of the function func(), such as break cb_button
delete breakpoint number n: deletes the nth breakpoint
disable breakpoint No.: pause the nth breakpoint
enable breakpoint No.: open the nth breakpoint
Clear line number n: clear the breakpoint on line n
info b (info breakpoints): displays the breakpoint settings of the current program
delete breakpoints: clear all breakpoints:

3. View source code

List: abbreviated as l, its function is to list the source code of the program. By default, 10 lines are displayed each time.
list line number: the first and last 10 lines of code centered on "line number" of the current file will be displayed, such as: list 12
list function name: the source code of the function where the "function name" is located will be displayed, such as: list main
List: without parameters, the following contents will be output after the last list command.

4. Print expression

print expression: abbreviated as p, where "expression" can be a valid expression of any program currently being tested, such as a program currently debugging C language, and "expression" can be a valid expression of any C language, including numbers, variables and even function calls.
print a: the value of integer a will be displayed
print ++a: the value in a will be increased by 1 and displayed
print name: the value of the string name will be displayed
print gdb_test(22): GDB will be called with integer 22 as parameter_ Test() function
print gdb_test(a): GDB will be called with variable a as a parameter_ Test() function
Display expression: it will be very useful in single step operation. After setting an expression with the display command, it will output the set expression and value immediately after each single step instruction. For example: display a
Watch expression: set a monitoring point. Once the value of the monitored "expression" changes, gdb will forcibly terminate the program being debugged. For example: watch a
whatis: query variables or functions
info function: query function
Extended info locals: displays all variables of the current stack page

5. View operation information

where/bt: stack list currently running;
bt backtrace displays the current call stack.
up/down changes the depth of the stack display
set args parameter: Specifies the parameters of the runtime
show args: view the set parameters
info program: to check whether the program is running, the process number, and the reason for being suspended.

6. Split window

layout: used to split the window. You can view the code and test it at the same time:
layout src: displays the source code window
layout asm: displays the Disassembly window
layout regs: displays the source / disassembly and CPU register windows
layout split: displays the source code and Disassembly window
Ctrl + L: refresh window

Topics: C++ Linux printf