当前位置: 首页 > Linux

printfsegmenterror(coredump)-aproblemcausedbyaformattedoutput

时间:2023-04-06 22:08:28 Linux

1、printfsegmenterror(coredump):aproblembyaformattedoutput贴个简单的例子:#includeintmain(){intlen=sizeof(int);printf("%s\n",len);return0;}`root@ubuntu:test#gcctest.ctest.c:在函数'main':test中。c:5:2:警告:格式“%s”需要类型为“char*”的参数,但参数2的类型为“int”[-Wformat=]printf("%s\n",len);^``root@ubuntu:test#./a.outSegmentationfault(coredumped)`因为工程文件比较大,用Makefile编译的时候没有注意一些重要的编译警告,还升级了版本.折腾了两三天才发现是我用gdb调试的,发现果然是printf导致了我自己的程序段错误。发布项目gdb运行错误:名为CoreThread的线程收到信号段错误(gdb)btThread12“CoreThread”收到信号SIGSEGV,分段错误。[切换到线程0x7fffed7fa700(LWP21396)]0x00007ffff6d95cd0in_IO_vfprintf_internal(s=10c7ff2_IO_2_>1_std_>1_,format=,ap=ap@entry=0x7fffed7f9cf8)atvfprintf.c:16321632vfprintf.c:Nosuchfileordirectory.2.使用gdb的“bt”命令显示当前调用栈(gdb)bt#00x00007ffff6d95cd0in_IO_vfprintf_internal(s=0x7ffff710c620<_IO_2_1_stdout_>,format=,ap=ap@entry=0x7fffed7f9cf8)atvfprintf.c:1632#10x00007ffff6e5daefin___printf_chk(flag=1,format=)atprintf_chk.c:35#20x000000000041f10cinprintf(__fmt=0x5b3bc0"%s,startPushStream成功,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#3StartPushStream(channelId=channelid@entry=0,session=session@entry=0x7fffed7f9ea0,type=type@entry=SDK_LV_STREAM_CMD_LIVE)atnvr_demo/nvrCallback.cpp:235#40x000000000042004cinNvrStartPushStreamingCb(channelId=0,session=0x7fffed7f9amon0ffde07,param0v04c)/nvrCallback.cpp:584#50x0000000000417140在StartNvrPushStreamingCb(auth=0x1407f80,param=0x7fffd400be20)在../src/core_cb/cb_to_cloud.c:885#60x00000000004626:885#60x00000000004626:19在linkProcessual(voidProcessual)Job:19#70x00007ffff71186bainstart_thread(arg=0x7fffed7fa700)atpthread_create.c:333#80x00007ffff6e4e51dinclone()at../sysdeps/unix/sysv/linux/x86_64/clone.S:109(gdb)3.查找原因错误的根据gdb当前的调用栈信息,我们定位到第2行,找到函数startPushStream中的printf,发现新版本中session_id的类型是int,而这里的print使用的是%s,导致段错误,由于老版本的session_id类型是char*,所以没有报错。当自己的程序出现段错误时,灵活使用gdb可以加快定位错误的速度,节省时间,而不用加打印这种繁琐的调试定位方法。四、gdb的一些常用方法有1、运行命令run:缩写为r,其作用是运行程序。当遇到断点时,程序会在断点处停止运行,等待用户输入下一条命令。continue(简写c):继续执行到下一个断点(或运行结束)next:(简写n),单步跟踪程序,遇到函数调用时,不会进入函数体;this命令与step的主要区别在于,step遇到用户自定义函数时,会单步进入函数运行,而next则直接调用函数,不进入函数体。step(缩写s):单步调试如果有函数调用,则进入函数;与命令n不同的是,n是直到:当你厌倦了在循环体中单步跟踪时才进入被调用的函数,这个命令可以让程序继续运行直到退出循环体。until+linenumber:运行到某一行,不仅跳出循环finish:运行程序直到当前函数返回,并打印函数返回时的栈地址、返回值、参数值等信息。callfunction(parameter):调用程序中可见的函数,并传递“parameter”,如:callgdb_test(55)quit:简写为q,退出gdb2,设置断点breakn(简写为bn):linensetabreakpointat(可以带上代码路径和代码名:bOAGUPDATE.cpp:578)bfn1ifa>b:条件断点设置breakfunc(break简写为b):设置在函数入口func()断点,如:breakcb_buttondeleteBreakpointnumbern:删除第n个断点disableBreakpointnumbern:暂停第n个断点enableBreakpointnumbern:启用第n个断点clearLinenumbern:清除第n个断点Linebreakpointsinfob(infobreakpoints):显示当前程序的断点设置deletebreakpoints:清除所有断点:3.查看源代码列表:缩写为l,其功能是列出程序的源代码。一次显示10行。list行号:会以“行号”为中心显示当前文件前后10行代码,如:list12list函数名:会显示“函数名”所在函数的源代码,如:listmainlist:不带参数,会跟随前面的list命令,输出如下内容。4.打印表达式打印表达式:简写为p,其中“表达式”可以是当前被测试程序的任何有效表达式,比如C语言当前正在调试的程序,那么“表达式”可以是任何C语言的有效表达式语言,包括数字、变量甚至函数调用。printa:将显示整数a的值print++a:将a中的值加1并显示它printname:将显示字符串name的值printgdb_test(22):将使用整数调用gdb_test22asaparameter()functionprintgdb_test(a):会以变量a为参数调用gdb_test()函数expression,会在每个单步执行命令后,立即输出设置的表达式和值。如:displayawatchexpression:设置一个监视点,一旦被监视的“expression”的值发生变化,gdb将强行终止正在调试的程序。如:watchawhatis:查询变量或函数信息function:查询函数扩展信息locals:显示当前栈页的所有变量5、查看运行信息where/bt:当前运行栈列表;btbacktrace显示当前调用栈上下变化栈深度显示setargsparameters:指定运行时的参数showargs:查看设置的参数infoprogram:查看程序是否运行,进程号,以及被停职的原因。6.Splitwindowlayout:用于分割窗口,测试时可以查看代码:layoutsrc:显示源码窗口layoutasm:显示反汇编窗口layoutregs:显示源码/反汇编和CPU寄存器windowlayoutsplit:显示Source代码和反汇编窗口Ctrl+L:刷新窗口