日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C和C++中的野指针问题

發(fā)布時間:2025/4/5 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C和C++中的野指针问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

    • 1 C和C++中的野指針問題
      • 1.1 野指針的概念
      • 1.2 野指針的由來
      • 1.3 杜絕野指針的基本原則
    • 2 C和C++中的常見內(nèi)存錯誤
      • 2.1 常見內(nèi)存錯誤
      • 2.2 內(nèi)存操作的基本規(guī)則

1 C和C++中的野指針問題

1.1 野指針的概念

野指針的概念:

  • 指針變量中的值是非法的內(nèi)存地址,進而形成野指針。
  • 野指針不是NULL指針,是指向不可用內(nèi)存地址的指針。
  • NULL指針并無危害,很好判斷,也很好調(diào)試。
  • C語言中無法判斷一個指針所保存的地址是否合法。

1.2 野指針的由來

如下情況可能導(dǎo)致野指針的出現(xiàn):

  • 局部指針變量沒有被初始化。
  • 指針所指向的變量在指針之前被銷毀(返回局部變量和局部數(shù)組)。
  • 使用已經(jīng)釋放過的指針。
  • 進行了錯誤的指針運算。
  • 進行了錯誤的強制類型轉(zhuǎn)換。

野指針初探:

#include <stdio.h> #include <malloc.h>int main() {int* p1 = (int*)malloc(40);int* p2 = (int*)1234567;//p2是一個野指針int i = 0;for(i=0; i<40; i++){*(p1 + i) = 40 - i;//由于指針運算產(chǎn)生了野指針,改寫了非法的內(nèi)容}free(p1); for(i=0; i<40; i++){p1[i] = p2[i];//使用了已經(jīng)釋放的內(nèi)存空間}return 0; }

1.3 杜絕野指針的基本原則

基本原則:

  • 絕不返回局部變量和局部數(shù)組的地址。
  • 任何變量在定義后必須0初始化。
  • 字符數(shù)組必須確認0結(jié)束符后才能成為字符串。
  • 任何使用與內(nèi)存相關(guān)的函數(shù)必須指定長度信息。

無處不在的野指針:

#include <stdio.h> #include <string.h> #include <malloc.h>struct Student {char* name;int number; };char* func() {char p[] = "D.T.Software";return p; }void del(char* p) {printf("%s\n", p);free(p); }int main() {struct Student s;//由于沒有初始化,產(chǎn)生野指針char* p = func();//產(chǎn)生了野指針strcpy(s.name, p); //使用野指針s.number = 99;p = (char*)malloc(5);strcpy(p, "D.T.Software");//產(chǎn)生內(nèi)存越界,操作了野指針所指向的內(nèi)存空間del(p);return 0; }

內(nèi)存錯誤是實際產(chǎn)品開發(fā)中最常見的問題,然而絕大多數(shù)的bug都可以通過遵循基本的編程原則和規(guī)范來避免。因此,在學(xué)習(xí)的的時候要牢記和理解內(nèi)存操作的基本原則,目的和意義。


2 C和C++中的常見內(nèi)存錯誤

2.1 常見內(nèi)存錯誤

常見內(nèi)存錯誤如下:

  • 結(jié)構(gòu)體成員指針未初始化。
  • 結(jié)構(gòu)體成員指針未分配足夠的內(nèi)存。
  • 內(nèi)存分配成功,但并未初始化。
  • 內(nèi)存操作越界。

常見內(nèi)存錯誤1:

#include <stdio.h> #include <malloc.h>void test(int* p, int size) {int i = 0;for(i=0; i<size; i++){printf("%d\n", p[i]);}free(p); }void func(unsigned int size) {int* p = (int*)malloc(size * sizeof(int));int i = 0;if( size % 2 != 0 ){return; }for(i=0; i<size; i++){p[i] = i;printf("%d\n", p[i]);}free(p); }int main() {int* p = (int*)malloc(5 * sizeof(int));test(p, 5);free(p); func(9);func(10);return 0; } /* 說明:兩次釋放同一個指針可能會讓程序崩潰,double free or corruption (fasttop): 0x0977b008 *** Aborted (core dumped)。 */

常見內(nèi)存錯誤2:

#include <stdio.h> #include <malloc.h>struct Demo {char* p; };int main() {struct Demo d1;struct Demo d2;char i = 0;for(i='a'; i<'z'; i++){d1.p[i] = 0; }d2.p = (char*)calloc(5, sizeof(char));printf("%s\n", d2.p);for(i='a'; i<'z'; i++){d2.p[i] = i; }free(d2.p);return 0; } // 說明:calloc申請出來的內(nèi)存會被全部置0。

2.2 內(nèi)存操作的基本規(guī)則

1.動態(tài)內(nèi)存申請之后,應(yīng)該立即檢查指針值是否為NULL,防止使用NULL指針。

2.free指針之后必須立即賦值為NULL。

3.任何與內(nèi)存操作相關(guān)的函數(shù)都必須帶長度信息。

補充: int snprintf(char restrict buf, size_t n, const char restrict
format, …);函數(shù)說明:最多從源串中拷貝n-1個字符到目標串中,然后再在后面加一個0。所以如果目標串的大小為n的話…
基本功能: 將可變個參數(shù)(…)按照format格式化成字符串,然后將其復(fù)制到str中 (1) 如果格式化后的字符串長度 <
size,則將此字符串全部復(fù)制到str中,并給其后添加一個字符串結(jié)束符(‘\0’); (2) 如果格式化后的字符串長度 >=
size,則只將其中的(size-1)個字符復(fù)制到str中,并給其后添加一個字符串結(jié)束符(‘\0’),返回值為格式化后的字符串的長度。
char a[20]; i = snprintf(a, 9, “%012d”, 12345);[1] printf(“i = %d, a =
%s”, i, a); 輸出為:i = 12, a = 00000001

4.malloc操作和free操作必須匹配,防止內(nèi)存泄漏和多次釋放。

內(nèi)存錯誤的本質(zhì)源于指針保存的地址為非法值:

  • 指針變量未初始化,保存隨機值;
  • 指針運算導(dǎo)致內(nèi)存越界。

內(nèi)存泄漏源于malloc和free不匹配:

  • 當(dāng)malloc次數(shù)多于free時,產(chǎn)生內(nèi)存泄漏;
  • 當(dāng)malloc次數(shù)少于free時,程序可能崩潰。
  • 應(yīng)對的措施:在哪個函數(shù)里申請就在哪個函數(shù)里釋放,不要跨函數(shù)釋放動態(tài)內(nèi)存空間。

參考資料:

  • C語言進階剖析教程
  • 總結(jié)

    以上是生活随笔為你收集整理的C和C++中的野指针问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。