499可以做網(wǎng)站百度廣告推廣平臺(tái)
目錄
1 野指針
1.1 成因
1.2 如何規(guī)避野指針
2 assert 斷言
2.1 用法
2.2?assert 的優(yōu)點(diǎn)
2.1?assert 的缺點(diǎn)
3 小注解
3.1 Debug 和 Release?
1 野指針
【概念】: 野指針就是指針指向的位置是不可知的(隨機(jī)的、不正確的、沒(méi)有明確限制的)
1.1 成因
(1)指針未初始化
(2)指針越界訪問(wèn)
//VS2022,x64
#include<stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 }; //arr[0]~arr[4]int* p = arr;for (int i = 0; i <= 5; i++) //當(dāng)i=5時(shí),*(p + i) 表示 arr[5],越界{printf("%d ", *(p + i)); //輸出結(jié)果 1 2 3 4 5 -858993460}return 0;
}
(3)指針指向的空間被釋放
#include <stdio.h>
int* test()
{int n = 100; //n為局部變量,當(dāng)函數(shù)調(diào)用結(jié)束,//n的空間也會(huì)被銷(xiāo)毀return &n;
}
int main()
{int* p = test();printf("%d\n", *p); //在VS上可以運(yùn)行,但是會(huì)報(bào)警告return 0;
}
1.2 如何規(guī)避野指針
(1)如果明確知道指針指向哪里就直接賦值地址,如果不知道指針應(yīng)該指向哪里,可以給指針賦值 NULL。
#include<stdio.h> //使用NULL必須包含這個(gè)頭文件
int main()
{int* p = NULL;return 0;
}
(2)小心指針越界
(3)指針變量不再使用時(shí),及時(shí)置NULL,指針使用之前檢查有效性
#include<stdio.h>
int main()
{int arr[5] = { 1,2,3,4,5 };int* p = &arr[0];int i = 0;for (i = 0; i < 5; i++){*(p++) = i; //先解引用再++}//此時(shí) *p 表示 arr[5],已經(jīng)越界p = NULL;//下次使?的時(shí)候,判斷p不為NULL的時(shí)候再使?//...p = &arr[0];//重新讓p獲得地址if (p != NULL) //判斷{//...}return 0;
}
(4)避免返回局部變量的地址,如造成野指針的第3個(gè)例子,不要返回局部變量的地址。
2 assert 斷言
2.1 用法
assert.h 頭文件定義了宏 assert() ,用于在運(yùn)行時(shí)確保程序符合指定條件,如果不符合,就報(bào)錯(cuò)終止運(yùn)行。這個(gè)宏常常被稱為“斷言”。
assert(p != NULL)
assert() 宏接受?個(gè)表達(dá)式作為參數(shù)。如果該表達(dá)式為真(返回值非零), assert() 不會(huì)產(chǎn)生任何作用,程序繼續(xù)運(yùn)行。如果該表達(dá)式為假(返回值為零), assert() 就會(huì)報(bào)錯(cuò),在標(biāo)準(zhǔn)錯(cuò)誤流 stderr 中寫(xiě)入一條錯(cuò)誤信息,顯示沒(méi)有通過(guò)的表達(dá)式,以及包含這個(gè)表達(dá)式的文件名和行號(hào)。
有同學(xué)會(huì)覺(jué)得這不就跟 if 一樣嗎,他的好處非常多,請(qǐng)接著往下看
2.2?assert 的優(yōu)點(diǎn)
assert() 的使用對(duì)程序員是非常友好的,
使用?assert() 有幾個(gè)好處:
- 能自動(dòng)標(biāo)識(shí) 文件 和 出問(wèn)題的行號(hào)
- 無(wú)需更改代碼就能開(kāi)啟或關(guān)閉 assert() 的機(jī)制。如果已經(jīng)確認(rèn)程序沒(méi)有問(wèn)題,不需要再做斷言,就在 #include 語(yǔ)句的前面,定義?個(gè)宏 NDEBUG 。?然后重新編譯程序,編譯器就會(huì)禁用文件中所有的 assert() 語(yǔ)句。如果程序又出現(xiàn)問(wèn)題,可以移除這條 #define NDEBUG 指令(或者把它注釋掉),再次編譯,這樣就重新啟用了 assert() 語(yǔ)句。
#define NDEBUG
#include <assert.h>
2.1?assert 的缺點(diǎn)
assert() 的缺點(diǎn)是,因?yàn)橐肓祟~外的檢查,增加了程序的運(yùn)行時(shí)間。
?般我們可以在 Debug 中使用,在 Release 版本中選擇禁用?assert 就行,在 VS 這樣的集成開(kāi) 發(fā)環(huán)境中,在 Release 版本中,直接就是優(yōu)化掉了。這樣在debug版本寫(xiě)有利于程序員排查問(wèn)題, 在 Release 版本不影響用戶使用時(shí)程序的效率。
3 小注解
3.1 Debug 和 Release?
在VS上編寫(xiě)代碼的時(shí)候,就能看到有 Debug 和 Release 兩個(gè)選項(xiàng),分別是什么意思呢?
Debug 通常稱為調(diào)試版本,它包含調(diào)試信息,并且不作任何優(yōu)化,便于程序員調(diào)試程序; 程序員在寫(xiě)代碼的時(shí)候,需要經(jīng)常性的調(diào)試代碼,就將這里設(shè)置為 debug ,這樣編譯產(chǎn)生的是 debug 版本的可執(zhí)行程序,其中包含調(diào)試信息,是可以直接調(diào)試的。
Release 稱為發(fā)布版本,它往往是進(jìn)行了各種優(yōu)化,使得程序在代碼大小和運(yùn)行速度上都是最優(yōu)的, 以便用戶很好地使用。當(dāng)程序員寫(xiě)完代碼,測(cè)試再對(duì)程序進(jìn)行測(cè)試,直到程序的質(zhì)量符合交付給用戶使用的標(biāo)準(zhǔn),這個(gè)時(shí)候就會(huì)設(shè)置為 release ,編譯產(chǎn)生的就是 release 版本的可執(zhí)行程序,這個(gè)版本是用戶使用的,無(wú)需包含調(diào)試信息等。
完