C++ coredump實例解析

一、背景

    經過重重調試後,看到編譯成功的那一刻,內心充滿歡喜。當程序一運行,卻經常出現coredump的情況,此時內心是崩潰的。我想程序員經常會碰到這種情況,尤其使用c++語言編寫代碼,由於沒有自動內存管理,經常會出現coredump情況,主要原因有以下幾類:

  1. 操作非法指針
  2. 內存訪問越界:索引越界、使用高危函數等
  3. 格式化輸出時數據類型錯誤
  4. 併發引起的問題:未加鎖保護;使用線程不安全函數
  5. 堆棧溢出

下面對這幾類進行分析

 

二、場景分析及解決方案

場景一

struct A {
char* str;
};
 
class B {
public:
    B() { str = NULL; val = -1;}
    B(const int& p_val);
    bool set(const int& value);
    bool get(const int& key, int& value);

private:
    int val;
};

int main() {
    A a;
    std::cout << "str = " << a.str << std::endl;

    B* aa = new B();
    const int val = 615;
    aa.set(val);        

    return 0;
}

注:代碼中set,get沒具體寫實現

問題描述

1)使用非法指針str會直接導致coredump,代碼多時,這種情況其實很難發現

2)new指針對象後直接使用,如果內存分配失敗,也會出現問題

解決方案

1)使用了非法指針,記住使用指針前務必判空,不管是對象指針、簡單類型對應的指針、函數指針等等

2)分配堆內存,需要判斷是否成功分配,還要記得手動釋放,也可以使用對象池、內存池、智能指針對指針對象進行自動管理

場景二

void test(const string& str, int idx) {
    std::cout << str[idx] << std::end;
}

int main() {
    int value[5] = {1, 2, 3, 4, 5};
    std::cout << value[5] << std::end;

    std::map<int, int> p_map;
    std::map<int, int>::iterator iter = p_map.find(20);
    std::cout << "value = " << iter->second;

    return 0;
}

問題描述

1)使用數組數據時,沒有判斷索引的有效性;使用stl容器,迭代器沒有判斷end()直接用

解決方案

1)使用數組或容器時,務必根據數組或容器的size檢查索引的有效性

場景三

// 整型字符串格式輸出
int value = 615;
printf("value[%s]\n", value);

// 字符串字符形式賦值
char *str = 'dianjing';
printf("str[%s]\n", str);

問題描述

1)輸出日誌或進行格式化賦值時,會經常寫錯,如整型數據使用字符串輸出

2)字符串賦值時誤使用單引號進行賦值,編譯器會提示,但不會報錯,這樣即使使用try catch也catch不住這種coredump

解決方案

1)格式化輸出時,務必檢查數據類型和輸出格式的正確性,以及數據類型賦值的準確性

場景四

問題描述

1)當主線程中使用並行線程進行並行執行時,並行線程中主線程local數據爲空,不能用

解決方案

1)並行線程回調函數傳入主線程local數據,或創建併發數據,每個並行線程指向不同的併發數據

總結

    程序出現coredump,千萬不要慌,希望通過本文能快速定位問題,後續會截圖具體coredump,對core文件進行分析。

  • 使用指針前一定要判空
  • 使用容器時,務必檢查索引的有效性
  • 格式化數據時,檢查數據類型和輸出格式的正確性
  • 併發時,檢查數據的有效性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章