0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

什么是段錯(cuò)誤?

工程師 ? 來(lái)源:聚優(yōu)致成 ? 作者:聚優(yōu)致成 ? 2020-09-11 14:04 ? 次閱讀

來(lái)源:聚優(yōu)致成

一、什么是段錯(cuò)誤?一旦一個(gè)程序發(fā)生了越界訪問(wèn),cpu 就會(huì)產(chǎn)生相應(yīng)的保護(hù),于是 segmentation fault 就出現(xiàn)了,通過(guò)上面的解釋,段錯(cuò)誤應(yīng)該就是訪問(wèn)了不可訪問(wèn)的內(nèi)存。

這個(gè)內(nèi)存區(qū)要么是不存在的,要么是受到系統(tǒng)保護(hù)的,還有可能是缺少文件或者文件損壞。

二、段錯(cuò)誤產(chǎn)生的原因下面是一些典型的段錯(cuò)誤的原因:

非關(guān)聯(lián)化空指針——這是特殊情況由內(nèi)存管理硬件

試圖訪問(wèn)一個(gè)不存在的內(nèi)存地址(在進(jìn)程的地址空間)

試圖訪問(wèn)內(nèi)存的程序沒(méi)有權(quán)利(如內(nèi)核結(jié)構(gòu)流程上下文)

試圖寫(xiě)入只讀存儲(chǔ)器(如代碼段)

1、訪問(wèn)不存在的內(nèi)存地址

在C代碼,分割錯(cuò)誤通常發(fā)生由于指針的錯(cuò)誤使用,特別是在C動(dòng)態(tài)內(nèi)存分配。非關(guān)聯(lián)化一個(gè)空指針總是導(dǎo)致段錯(cuò)誤。

但野指針和懸空指針指向的內(nèi)存,可能會(huì)或可能不會(huì)存在,而且可能或不可能是可讀的還是可寫(xiě)的,因此會(huì)導(dǎo)致瞬態(tài)錯(cuò)誤。

#include 《stdio.h》int main (void){ int *ptr = NULL; *ptr = 0; return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

現(xiàn)在,非關(guān)聯(lián)化這些變量可能導(dǎo)致段錯(cuò)誤:非關(guān)聯(lián)化空指針通常會(huì)導(dǎo)致段錯(cuò)誤,閱讀時(shí)從野指針可能導(dǎo)致隨機(jī)數(shù)據(jù)但沒(méi)有段錯(cuò)誤,和閱讀從懸空指針可能導(dǎo)致有效數(shù)據(jù),然后隨機(jī)數(shù)據(jù)覆蓋。

2、訪問(wèn)系統(tǒng)保護(hù)的內(nèi)存地址

#include 《stdio.h》 int main (void){ int *ptr = (int *)0; *ptr = 100; return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

3、訪問(wèn)只讀的內(nèi)存地址

寫(xiě)入只讀存儲(chǔ)器提出了一個(gè) segmentation fault,這個(gè)發(fā)生在程序?qū)懭胱约旱囊徊糠执a段或者是只讀的數(shù)據(jù)段,這些都是由操作系統(tǒng)加載到只讀存儲(chǔ)器。

#include 《stdio.h》#include 《string.h》 int main (void){ char *ptr = “test”; strcpy (ptr, “TEST”); return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

#include 《stdio.h》 int main (void){ char *ptr = “hello”; *ptr = ‘H’; return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

上述例子ANSI C代碼通常會(huì)導(dǎo)致段錯(cuò)誤和內(nèi)存保護(hù)平臺(tái)。它試圖修改一個(gè)字符串文字,這是根據(jù)ANSI C標(biāo)準(zhǔn)未定義的行為。大多數(shù)編譯器在編譯時(shí)不會(huì)抓,而是編譯這個(gè)可執(zhí)行代碼,將崩潰。

包含這個(gè)代碼被編譯程序時(shí),字符串“hello”位于rodata部分程序的可執(zhí)行文件的只讀部分?jǐn)?shù)據(jù)段。

當(dāng)加載時(shí),操作系統(tǒng)與其他字符串和地方常數(shù)只讀段的內(nèi)存中的數(shù)據(jù)。當(dāng)執(zhí)行時(shí),一個(gè)變量 ptr 設(shè)置為指向字符串的位置,并試圖編寫(xiě)一個(gè)H字符通過(guò)變量進(jìn)入內(nèi)存,導(dǎo)致段錯(cuò)誤。

編譯程序的編譯器不檢查作業(yè)的只讀的位置在編譯時(shí),和運(yùn)行類unix操作系統(tǒng)產(chǎn)生以下運(yùn)行時(shí)發(fā)生 segmentation fault。

可以糾正這個(gè)代碼使用一個(gè)數(shù)組而不是一個(gè)字符指針,這個(gè)棧上分配內(nèi)存并初始化字符串的值:

#include 《stdio.h》 int main (void){ char ptr[] = “hello”; ptr[0] = ‘H’; return 0;}

即使不能修改字符串(相反,這在C標(biāo)準(zhǔn)未定義行為,在C char *類型,所以沒(méi)有隱式轉(zhuǎn)換原始代碼,在c++的 const char *類型,因此有一個(gè)隱式轉(zhuǎn)換,所以編譯器通常會(huì)抓住這個(gè)特定的錯(cuò)誤。

4、空指針廢棄

因?yàn)槭且粋€(gè)很常見(jiàn)的程序錯(cuò)誤空指針廢棄(讀或?qū)懺谝粋€(gè)空指針,用于C的意思是“沒(méi)有對(duì)象指針”作為一個(gè)錯(cuò)誤指示器),大多數(shù)操作系統(tǒng)內(nèi)存訪問(wèn)空指針的地址,這樣它會(huì)導(dǎo)致段錯(cuò)誤。

#include 《stdio.h》 int main (void){ int *ptr = NULL; printf (“%d\n”, *ptr); return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

這個(gè)示例代碼創(chuàng)建了一個(gè)空指針,然后試圖訪問(wèn)它的值(讀值)。在運(yùn)行時(shí)在許多操作系統(tǒng)中,這樣做會(huì)導(dǎo)致段錯(cuò)誤。

非關(guān)聯(lián)化一個(gè)空指針,然后分配(寫(xiě)一個(gè)值到一個(gè)不存在的目標(biāo))也通常會(huì)導(dǎo)致段錯(cuò)誤。

#include 《stdio.h》 int main (void){ int *ptr = NULL; *ptr = 1; return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

下面的代碼包含一個(gè)空指針,但當(dāng)編譯通常不會(huì)導(dǎo)致段錯(cuò)誤,值是未使用的。因此,廢棄通常會(huì)被優(yōu)化掉,死代碼消除。

#include 《stdio.h》 int main (void){ int *ptr = NULL; *ptr; return 0;}

還有,比如malloc 動(dòng)態(tài)分配內(nèi)存,釋放、置空完成后,不可再使用該指針。

#include 《stdio.h》#include 《stdlib.h》#include 《string.h》 int main(){ char* str=(char* )malloc(100); if(*str) { return; } strcpy(str,“hello”); printf(“%s\n”,str); free(str); str=NULL; strcpy(str,“abcdef”); return 0;}輸出結(jié)果:hello段錯(cuò)誤 (核心已轉(zhuǎn)儲(chǔ))

5、堆棧溢出

#include 《stdio.h》#include 《string.h》 int main (void){ main (); return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

上述例子的無(wú)限遞歸,導(dǎo)致的堆棧溢出會(huì)導(dǎo)致段錯(cuò)誤,但無(wú)線遞歸未必導(dǎo)致堆棧溢出,優(yōu)化執(zhí)行的編譯器和代碼的確切結(jié)構(gòu)。在這種情況下,遙不可及的代碼(返回語(yǔ)句)行為是未定義的。

因此,編譯器可以消除它,使用尾部調(diào)用優(yōu)化,可能導(dǎo)致沒(méi)有堆棧使用。其他優(yōu)化可能包括將遞歸轉(zhuǎn)換成迭代,給出例子的結(jié)構(gòu)功能永遠(yuǎn)會(huì)導(dǎo)致程序運(yùn)行,雖然可能不是其他堆棧溢出。

6、內(nèi)存越界(數(shù)組越界,變量類型不一致等)

#include 《stdio.h》int main (void){ char test[10]; printf (“%c\n”, test[100000]); return 0;}輸出結(jié)果:段錯(cuò)誤(核心已轉(zhuǎn)儲(chǔ))

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7605

    瀏覽量

    136936
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3616

    瀏覽量

    93763
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    EEPROM編程常見(jiàn)錯(cuò)誤及解決方案

    EEPROM(電可擦可編程只讀存儲(chǔ)器)在編程過(guò)程中可能會(huì)遇到多種錯(cuò)誤。以下是一些常見(jiàn)的EEPROM編程錯(cuò)誤及其解決方案: 常見(jiàn)錯(cuò)誤 數(shù)據(jù)寫(xiě)入錯(cuò)誤 : 在寫(xiě)入EEPROM時(shí),數(shù)據(jù)可能由于
    的頭像 發(fā)表于 12-16 17:08 ?705次閱讀

    SQL錯(cuò)誤代碼及解決方案

    在SQL數(shù)據(jù)庫(kù)開(kāi)發(fā)和管理中,常見(jiàn)的錯(cuò)誤代碼及其解決方案可以歸納如下: 一、語(yǔ)法錯(cuò)誤(Syntax Errors) 錯(cuò)誤代碼 :無(wú)特定代碼,但通常會(huì)在錯(cuò)誤消息中明確指出是語(yǔ)法
    的頭像 發(fā)表于 11-19 10:21 ?1838次閱讀

    socket編程中的錯(cuò)誤處理技巧

    Socket編程是網(wǎng)絡(luò)編程的基礎(chǔ),它允許程序之間通過(guò)TCP/IP協(xié)議進(jìn)行通信。然而,網(wǎng)絡(luò)通信是不穩(wěn)定的,可能會(huì)遇到各種問(wèn)題,如網(wǎng)絡(luò)延遲、連接中斷、數(shù)據(jù)丟失等。 錯(cuò)誤處理的重要性 提高程序的健壯性
    的頭像 發(fā)表于 11-01 17:47 ?870次閱讀

    網(wǎng)關(guān)錯(cuò)誤是什么意思

    網(wǎng)關(guān)錯(cuò)誤是計(jì)算機(jī)網(wǎng)絡(luò)中一個(gè)常見(jiàn)且復(fù)雜的問(wèn)題,它通常發(fā)生在客戶端和服務(wù)器之間的通信過(guò)程中,導(dǎo)致客戶端的請(qǐng)求無(wú)法被正確處理或響應(yīng)。為了全面理解網(wǎng)關(guān)錯(cuò)誤,本文將從其定義、原因、類型、影響、診斷方法以及解決方案等多個(gè)方面進(jìn)行詳細(xì)闡述。
    的頭像 發(fā)表于 09-30 11:40 ?3364次閱讀

    SRAM中的錯(cuò)誤檢測(cè)

    電子發(fā)燒友網(wǎng)站提供《SRAM中的錯(cuò)誤檢測(cè).pdf》資料免費(fèi)下載
    發(fā)表于 09-20 11:15 ?0次下載
    SRAM中的<b class='flag-5'>錯(cuò)誤</b>檢測(cè)

    CAN總線錯(cuò)誤狀態(tài)的種類

    CAN總線錯(cuò)誤狀態(tài)的種類主要包括以下幾種,每種狀態(tài)都反映了CAN總線網(wǎng)絡(luò)中節(jié)點(diǎn)或總線的不同錯(cuò)誤情況,以及相應(yīng)的通信能力和限制。
    的頭像 發(fā)表于 09-03 14:17 ?1449次閱讀

    【飛凌嵌入式OK527N-C開(kāi)發(fā)板體驗(yàn)】3.鼠標(biāo)+硬件編解碼+音頻播放器

    有偶而的報(bào)錯(cuò),且運(yùn)行一時(shí)間 會(huì)有明顯卡頓,懷疑是加載一,解碼一。 測(cè)試音頻播放,啟動(dòng)后可以 顯示 出播放器畫(huà)面,但我沒(méi)鼠標(biāo)無(wú)法播放,但神奇的地方是我這個(gè)屏幕有觸摸,點(diǎn)按時(shí)會(huì)導(dǎo)致
    發(fā)表于 07-25 23:47

    一文讀懂CAN通訊錯(cuò)誤

    CAN總線通信技術(shù)廣泛應(yīng)用于多個(gè)行業(yè),是每個(gè)總線設(shè)計(jì)工程師必學(xué)的一個(gè)通訊網(wǎng)絡(luò)。然而,對(duì)于CAN通信中的錯(cuò)誤幀,許多人僅停留在表面了解,缺乏深入理解,這導(dǎo)致許多工程師在面對(duì)總線通信故障時(shí)感到無(wú)從下手
    的頭像 發(fā)表于 06-12 08:24 ?2729次閱讀
    一文讀懂CAN通訊<b class='flag-5'>錯(cuò)誤</b>幀

    使用sophon-demo_v0.1.8_dbb4632_20231116下面的YOLOv8中的yolov8_bmcv歷程出現(xiàn)錯(cuò)誤的原因?

    使用sophon-demo_v0.1.8_dbb4632_20231116下面的YOLOv8中的yolov8_bmcv歷程,出現(xiàn)錯(cuò)誤: 定位到代碼中出錯(cuò)的函數(shù)是 picDec(h, img_file.c_str(), bmimg);這是什么原因呢?這個(gè)函數(shù)是算能提供的代
    發(fā)表于 05-30 07:37

    鴻蒙OpenHarmony:【 hb安裝異常處理】

    hb安裝過(guò)程中出現(xiàn)亂碼、錯(cuò)誤
    的頭像 發(fā)表于 04-30 16:28 ?789次閱讀
    鴻蒙OpenHarmony:【 hb安裝異常處理】

    一文讀懂CAN控制器錯(cuò)誤處理的原理

    CAN通訊的錯(cuò)誤幀到底是如何被界定的?本文帶你輕松了解!錯(cuò)誤標(biāo)定檢測(cè)到錯(cuò)誤條件的站通過(guò)發(fā)送錯(cuò)誤標(biāo)志指示錯(cuò)誤。對(duì)于“
    的頭像 發(fā)表于 04-26 08:25 ?1626次閱讀
    一文讀懂CAN控制器<b class='flag-5'>錯(cuò)誤</b>處理的原理

    ucosiii的串口打印輸出遇到了硬件錯(cuò)誤怎么解決?

    我練兩天調(diào)試了ucos-iii之前是應(yīng)為一些問(wèn)題發(fā)現(xiàn)系統(tǒng)運(yùn)行錯(cuò)誤,但是到了第二天打開(kāi)工程從新編譯下載程序測(cè)試,發(fā)現(xiàn)一剛剛開(kāi)始打印串口消息就出現(xiàn)了硬件錯(cuò)誤錯(cuò)誤),懷疑是使用了半主機(jī)模
    發(fā)表于 04-24 06:03

    應(yīng)用程序中的服務(wù)器錯(cuò)誤怎么解決?

    在使用應(yīng)用程序時(shí),可能會(huì)遇到服務(wù)器錯(cuò)誤的問(wèn)題。這種錯(cuò)誤通常會(huì)導(dǎo)致應(yīng)用程序無(wú)法正常運(yùn)行 ,給用戶帶來(lái)不便。下面將介紹應(yīng)用程序中的服務(wù)器錯(cuò)誤及其解決方法,幫助您快速解決這一問(wèn)題。
    的頭像 發(fā)表于 03-12 15:13 ?6260次閱讀

    盤(pán)點(diǎn)PCB設(shè)計(jì)中的常見(jiàn)錯(cuò)誤

    搞技術(shù),難免存在錯(cuò)誤,只有經(jīng)歷過(guò)錯(cuò)誤,才能更快地成長(zhǎng)。PCB設(shè)計(jì)也一樣,今天就來(lái)盤(pán)點(diǎn)一下PCB設(shè)計(jì)中最常見(jiàn)的錯(cuò)誤。
    的頭像 發(fā)表于 01-12 09:53 ?1417次閱讀
    盤(pán)點(diǎn)PCB設(shè)計(jì)中的常見(jiàn)<b class='flag-5'>錯(cuò)誤</b>

    bm_image轉(zhuǎn)cv::Mat時(shí)出現(xiàn)錯(cuò)誤的原因?

    bm_image轉(zhuǎn)cv::Mat時(shí)出現(xiàn)錯(cuò)誤,堆棧信息如下:
    發(fā)表于 01-10 07:27