淺談 C++ 中的Segmentation Fault 錯誤

更新於 發佈於 閱讀時間約 5 分鐘
在工作中遇到的問題實在是千奇百怪,跟C++搏鬥了好一陣子了,仍然還是跟它不是很熟,最近工作上更遇到了bug之王的segmentation fault錯誤,雖然還沒找出root cause,不過在找了一陣子未果後,想說透過更系統性的方法來調查甚麼原因會導致segmentation fault。

何謂 Segmentation fault (記憶體區段錯誤)?

記憶體區段錯誤,也稱存取權限衝突(access violation),它會出現在當程式企圖存取CPU無法定址的記憶體區段時。當錯誤發生時,硬體會通知作業系統產生了記憶體存取權限衝突的狀況。作業系統通常會產生核心轉儲(core dump)以方便開發者進行除錯。
因此,即便當下通過編譯,也有可能在執行程式的期間,由於記憶體位置存取不當而發生這類型的錯誤,錯誤訊息通常為 “Access Violation Writing Location"。
以下Grant整理了幾種會導致Segmentation fault 的情況。

(1)錯誤的訪問寫入至唯讀記憶體

#include<stdio.h> 
#include<stdlib.h> 
int main() {     
   char *c = "hello world";    
   c[1] = 'H';
}
基本上當一個字元指標常量宣告並賦值後,就會被儲存於唯獨記憶體中,而試圖寫入至唯讀記憶體段會引發區段錯誤。因此,為了避免這種狀況,建議在常數前加上const,這樣在編譯階段,編譯器就會報錯了。

(2)訪問了不屬於程式地址空間的內存

指標在宣告後,必須指向對應的位址,但對於寫入受保護的位址,是不被允許的。
linux 位址上的頂部的四分之一是保留给內部核心的。即 0xffffffff 到 0xc0000000 是不可存取的地址,而下面的 0xc0000fff 即是在這區間。
#include <stdio.h>   
#include <stdlib.h>  
int main() {           
  int *p = (int*)0xC0000fff;           
  *p = 10;   
}

(3)寫入空指標

空指標(0 or NULL)時所指向的記憶體位址是受到保護的,所以一旦遭到強行寫入,都會發生區段錯誤。
#include <stdio.h>  
#include <stdlib.h> 
#include <iostream> 
int main(){      
int *i=0;     
  std::cout << &i;     
  scanf ("%d", i);     
  printf ("%d\n", i); 
}

(4)越界存取

再來一個常見引起區段錯誤的原因即是越界存取不存在的數組,例如以下的程式碼中,只宣告了長度為10的char,卻要印出c的位於第180000的資料。
#include <stdio.h>  
#include <stdlib.h> 
#include <iostream> 
int main() {      
  char c[10];      
  printf("%c", c[180000]);  
}
以上就是一些關於Segmentation fault的知識,一開始對於這個錯誤毫無頭緒,再做過了一些調查也實際上 replicate issue 的 scenarios 之後,總算有點概念了,如果之後有找到工作上遇到的那個問題的root cause,Grant 會再來這裡更新一下。
C++在管理內存較其他語言來說,彈性相當高,這是個兩面刃,一旦對於內存不熟悉,就很有可能corrupt掉整個系統,因此在寫的時候要更加小心。
————–更新——————
後來發現的 root cause 是由於寫入不存在的記憶體。
舉例來說,就是程式中有個兩個陣列,有一個陣列裡面是存要使用的方法的位置,另一個是類似定義要讀檔的 enum,藉由 enum 陣列與方法陣列的 index 來 mapping對應的使用情境。
但這兩個陣列的的內容不匹配,也就是長度不同。例如第一個陣列長度 11,而第二個長度是 12,所以當程式今天讀到第 12 個位置的時候,沒有找到對應的方法的位址的定義,並且在寫入的時候噴錯,因為根本沒有辦法分配對應的位址給不存在的方法。不過,只要是讀1-11的定義都不會有事,也導致在特定情況時才會報出區段錯誤,解法就是把長度為 11 的陣列增加為 12 並分派對應的方法的 address。
avatar-img
14會員
17內容數
還在為不知道怎麼面試而煩惱嗎? 還在為苦無面試機會而沮喪嗎? 別擔心~讓我們一起面對! 在專題中,我將以自身經驗傳授如何撰寫履歷以及分享面試經驗。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本章介紹了 PHP 中的例外處理技術,包括其語法、常見異常類型以及如何主動觸發異常訊息。我們還學習了如何自定義異常類別,以便更好地管理和處理不同類型的異常情況。通過使用例外處理,可以提高程式碼的穩定性、可讀性和可維護性,並提供更優雅的錯誤信息處理機制。
Thumbnail
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
Thumbnail
當你在開發程式時,難免會遇到各種錯誤和異常情況。這些錯誤可能是因為代碼中的錯誤、外部資源無法訪問或其他不可預期的狀況。為了提高程式的可靠性、穩定性和可維護性,我們使用「例外處理」來處理這些異常情況。
Thumbnail
本章節介紹C#的「例外處理」,包括使用try-catch語法處理錯誤,finally關鍵字的使用,以及如何主動引發和自定義異常。
Thumbnail
例外處理是Python中的重要概念,用於控制並處理程序異常,防止程序崩潰和數據損失。它包括try, except, else和finally等語法結構,可用於對特定錯誤進行處理,或主動觸發和自定義異常。
Thumbnail
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
本章介紹了 PHP 中的例外處理技術,包括其語法、常見異常類型以及如何主動觸發異常訊息。我們還學習了如何自定義異常類別,以便更好地管理和處理不同類型的異常情況。通過使用例外處理,可以提高程式碼的穩定性、可讀性和可維護性,並提供更優雅的錯誤信息處理機制。
Thumbnail
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
Thumbnail
當你在開發程式時,難免會遇到各種錯誤和異常情況。這些錯誤可能是因為代碼中的錯誤、外部資源無法訪問或其他不可預期的狀況。為了提高程式的可靠性、穩定性和可維護性,我們使用「例外處理」來處理這些異常情況。
Thumbnail
本章節介紹C#的「例外處理」,包括使用try-catch語法處理錯誤,finally關鍵字的使用,以及如何主動引發和自定義異常。
Thumbnail
例外處理是Python中的重要概念,用於控制並處理程序異常,防止程序崩潰和數據損失。它包括try, except, else和finally等語法結構,可用於對特定錯誤進行處理,或主動觸發和自定義異常。
Thumbnail
C 語言的函式庫定義了許多好用的函式,在寫 C++ 的時候可以拿來用。這是因為 C++ 當初在設計的時候,就有刻意把 C 涵蓋進來。 基本用法 首先要導入 C 語言的標準函式庫: #include <cstdlib> 以 c 作為開頭表示它是 C 語言的函式庫,只是被我們拿來 C++ 的程式
Thumbnail
讀取ini配置文件時如果某個參數不存在,它就會報錯,要怎麼避免呢? 可以使用fallback 參數來指定預設值。 這樣即使配置文件中缺少一些參數,我們的程序也能正常運行並使用預設值。 讓我們來假設一個案例做說明: 先故意將先前範例的port的資料刪掉。