C语言:段错误产生原因及简单的调试方法
生活随笔
收集整理的這篇文章主要介紹了
C语言:段错误产生原因及简单的调试方法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
段錯誤產生原因
1.訪問不存在的內存地址
如下面代碼,ptr沒有申請空間就直接拷貝數據:
#include?<stdio.h> #include?<string.h> #include?<stdlib.h>int?main(int?argc,?char?*argv[]) {char?*ptr?=?NULL;//This is the wrong implementation:strncpy(ptr,?"abc",?3);//ptr沒有申請空間就直接使用//The?right?way://ptr?=?(char?*)malloc(sizeof(char)?*?10);//memset(ptr,?0,?10);//strncpy(ptr,?"abc",?3);return?0; }2.訪問只讀的內存地址
錯誤做法:往字符串常量空間拷貝新的數據
#include?<stdlib.h> #include?<stdio.h> #include?<string.h>int?main(int?argc,?char?*argv[]) {char?*ptr?=?"test";strcpy(ptr,?"TEST1");return?0; }3.訪問系統保護的內存地址
如:
#include?<stdio.h>int?main(int?argc,?char?*argv[]) {int?*ptr?=?(int?*)0;*ptr?=?100;return?0; }4.棧溢出
如:
#include?<stdlib.h> #include?<stdio.h> #include?<string.h>int?main(int?argc,?char?*argv[]) {main(argc,?argv); }初學時兩種常用的段錯誤調試方法
1.使用printf輸出調試信息
這個是看似最簡單但往往很多情況下是十分有效的調試方式,也許可以說是程序員用的最多的調試方式。簡單來說,就是在程序的重要代碼附近加上printf輸出信息,這樣可以跟蹤并打印出段錯誤在代碼中最可能出現的位置。
使用案例:
以下面這段錯誤代碼為例:
#include?<stdio.h> #include?<string.h> #include?<stdlib.h>int?main(int?argc,?char?*argv[]) {char?*ptr?=?NULL;//This is the wrong implementation:strncpy(ptr,?"abc",?3);//ptr沒有申請空間就直接使用return?0; }可以在代碼中添加printf調試信息:
#include?<stdio.h> #include?<string.h> #include?<stdlib.h>int?main(int?argc,?char?*argv[]) {printf("line:%d\n",?__LINE__);?//單純打印代碼行數char?*ptr?=?NULL;//This is the wrong implementation:printf("line:%d\n",?__LINE__);?//單純打印代碼行數strncpy(ptr,?"abc",?3);//ptr沒有申請空間就直接使用printf("line:%d\n",?__LINE__);?//單純打印代碼行數return?0; }編譯運行后,會有如下輸出:
line:7 line:10 Segmentation?fault?(core?dumped)通過日志信息,就可以看到strncpy(ptr, "abc", 3);語句沒有被執行,我們就可以根據定位到的位置來排除ptr是否是未分配空間或者分配的空間不足引發的問題
2.使用gcc和gdb
調試步驟:
1、為了能夠使用gdb調試程序,在編譯階段加上-g參數,還是以下面這段錯誤代碼為例:
#include?<stdio.h> #include?<string.h> #include?<stdlib.h>int?main(int?argc,?char?*argv[]) {char?*ptr?=?NULL;//This is the wrong implementation:strncpy(ptr,?"abc",?3);//ptr沒有申請空間就直接使用return?0; }編譯代碼添加-g選項
gcc?-g?-o?test?test.c編譯出test程序,然后用gdb調試:
linux@linux:~/test$?gdb?./test GNU?gdb?(Ubuntu?8.1-0ubuntu3)?8.1.0.20180409-git Copyright?(C)?2018?Free?Software?Foundation,?Inc. License?GPLv3+:?GNU?GPL?version?3?or?later?<http://gnu.org/licenses/gpl.html> This?is?free?software:?you?are?free?to?change?and?redistribute?it. There?is?NO?WARRANTY,?to?the?extent?permitted?by?law.??Type?"show?copying" and?"show?warranty"?for?details. This?GDB?was?configured?as?"x86_64-linux-gnu". Type?"show?configuration"?for?configuration?details. For?bug?reporting?instructions,?please?see: <http://www.gnu.org/software/gdb/bugs/>. Find?the?GDB?manual?and?other?documentation?resources?online?at: <http://www.gnu.org/software/gdb/documentation/>. For?help,?type?"help". Type?"apropos?word"?to?search?for?commands?related?to?"word"... Reading?symbols?from?./test...done. (gdb)?r Starting?program:?/home/linux/test/test?Program?received?signal?SIGSEGV,?Segmentation?fault. 0x0000555555554611?in?main?(argc=1,?argv=0x7fffffffe528)?at?test.c:9 9???????????????????????????????strncpy(ptr,?"abc",?3);//ptr沒有申請空間就直接使用 (gdb)?quit A?debugging?session?is?active.Inferior?1?[process?15829]?will?be?killed.Quit?anyway??(y?or?n)?y從輸出看出,程序到SIGSEGV信號,觸發段錯誤,并提示地址0x0000555555554611以及代碼第9行出錯。
當然,還有利用core文件和gdb配置配合調試、使用objdump以及catchsegv命令的其他更為復雜的調試手段,這里就不展開講。
總結
以上是生活随笔為你收集整理的C语言:段错误产生原因及简单的调试方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【LINUX C 写文件】
- 下一篇: ansys linux17.2 字体,u