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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++中的野指针问题

發布時間:2023/12/18 c/c++ 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++中的野指针问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄
1 C和C++中的野指針問題
1.1 野指針的概念
1.2 野指針的由來
1.3 杜絕野指針的基本原則
2 C和C++中的常見內存錯誤
2.1 常見內存錯誤
2.2 內存操作的基本規則
1 C和C++中的野指針問題
1.1 野指針的概念
野指針的概念:

指針變量中的值是非法的內存地址,進而形成野指針。
野指針不是NULL指針,是指向不可用內存地址的指針。
NULL指針并無危害,很好判斷,也很好調試。
C語言中無法判斷一個指針所保存的地址是否合法。
1.2 野指針的由來
如下情況可能導致野指針的出現:

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

#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;//由于指針運算產生了野指針,改寫了非法的內容
? ? }

? ? free(p1);?

? ? for(i=0; i<40; i++)
? ? {
? ? ? ? p1[i] = p2[i];//使用了已經釋放的內存空間
? ? }

? ? return 0;
}


1.3 杜絕野指針的基本原則
基本原則:

絕不返回局部變量和局部數組的地址。
任何變量在定義后必須0初始化。
字符數組必須確認0結束符后才能成為字符串。
任何使用與內存相關的函數必須指定長度信息。
無處不在的野指針:

#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;//由于沒有初始化,產生野指針
? ? char* p = func();//產生了野指針

? ? strcpy(s.name, p); //使用野指針

? ? s.number = 99;

? ? p = (char*)malloc(5);

? ? strcpy(p, "D.T.Software");//產生內存越界,操作了野指針所指向的內存空間

? ? del(p);

? ? return 0;
}


內存錯誤是實際產品開發中最常見的問題,然而絕大多數的bug都可以通過遵循基本的編程原則和規范來避免。因此,在學習的的時候要牢記和理解內存操作的基本原則,目的和意義。

2 C和C++中的常見內存錯誤
2.1 常見內存錯誤
常見內存錯誤如下:

結構體成員指針未初始化。
結構體成員指針未分配足夠的內存。
內存分配成功,但并未初始化。
內存操作越界。
常見內存錯誤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)。
*/

常見內存錯誤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申請出來的內存會被全部置0。


2.2 內存操作的基本規則
1.動態內存申請之后,應該立即檢查指針值是否為NULL,防止使用NULL指針。

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

3.任何與內存操作相關的函數都必須帶長度信息。


補充: int snprintf(char restrict buf, size_t n, const char restrict
format, …);函數說明:最多從源串中拷貝n-1個字符到目標串中,然后再在后面加一個0。所以如果目標串的大小為n的話…
基本功能: 將可變個參數(…)按照format格式化成字符串,然后將其復制到str中 (1) 如果格式化后的字符串長度 <
size,則將此字符串全部復制到str中,并給其后添加一個字符串結束符(‘\0’); (2) 如果格式化后的字符串長度 >=
size,則只將其中的(size-1)個字符復制到str中,并給其后添加一個字符串結束符(‘\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操作必須匹配,防止內存泄漏和多次釋放。


內存錯誤的本質源于指針保存的地址為非法值:

指針變量未初始化,保存隨機值;
指針運算導致內存越界。
內存泄漏源于malloc和free不匹配:

當malloc次數多于free時,產生內存泄漏;
當malloc次數少于free時,程序可能崩潰。
應對的措施:在哪個函數里申請就在哪個函數里釋放,不要跨函數釋放動態內存空間。
/**************************野指針產生的三種情況

C/C++中野指針產生的三種情況

?1、指針變量未初始化:

?任何指針變量剛被創建時不會自動成為NULL指針,它的缺省值是隨機的,它會亂指一氣,此時若未初始化,則產生野指針。

?2、指針釋放后未置空:

?有時指針在free或delete后未賦值 NULL,便會使人以為是合法的,此時指針指向一塊未定義、未分配的內存。其實free和delete只是把指針所指的內存給釋放掉,但并沒有把指針本身干掉。指針指向的就是“垃圾”內存。所以釋放后的指針應立即將指針置為NULL,防止產生“野指針”。

?3、指針操作超越變量作用域:

?不要返回指向棧內存的指針或引用,因為棧內存在函數結束時會被釋放。
?

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。