iOS 中這些是否熟練掌握——(2)

接上一篇博文,本篇博文是做者原創,用於記錄從網上查閱的一些資料,並對本身的知識體系進行一下總結,成文以供學習使用。html

1.Cocoa Touch 包含了什麼?不包含什麼?與 Cocoa 有什麼區別?ios

  • 相同之處:二者都包含OC運行時的兩個核心框架:算法

  • cocoa包含Foundation和AppKit框架,可用於開發Mac OS X系統的應用程序數據庫

  • cocoa touch包含Foundation和UIKit框架,可用於開發iPhone OS 系統的應用程序編程

  • Cocoa時Mac OS X的開發環境,cocoa Touch是 Iphone OS的開發環境json

 

2.響應者連是什麼(Responder chain)?他是如何發揮做用的?segmentfault

凡是直接或者間接的繼承自 UIResponder 類建立的對象都是相應者,如:UIView、UIViewController 、UIApplication 由響應者對象組成的鏈叫響應者連。設計模式

在視圖被觸摸的時候,系統會有碰撞檢測過程,查找該觸摸是發生在那個視圖上。緩存

UIApplication->UIViewController->UIView ->視圖1->視圖2->視圖3.性能優化

碰撞檢測以後,接下來對觸摸事件進行處理,首先去看視圖3是否對該事件做出相應,若是視圖3不處理,就看視圖2是否處理,以此往上面去請求詢問,直到該觸摸事件被處理,若是沒有任何視圖或者響應者對象去處理該觸摸事件,則丟棄對該觸摸事件的相應。

 

3.什麼是 method swizzling ? 參考

 method swizzling 就是改變一個已經存在的選擇器對應的實現過程,它依賴於OC中的方法的調用可以在運行時進行改變———經過改變類的調度表(dispatch_table)中選擇器到最終函數間的映射關係。

 

4.什麼是 Base64 、MD5 算法,什麼是對稱加密、什麼是非對稱加密 ?

 base64 是一種編碼方式,將3字節的數據按照6比特去從新分組,分紅4組,變成4字節的數據,高位使用0填充。通常用於電子郵件的編碼。

 MD5算法:

a.壓縮性:任意長度的數據,計算出的MD5值的長度都是固定的。

b.容易計算:從原數據計算出MD5值很容易。

c.抗修改性:對原來的數據,哪怕是修改了一個字節的數據,所獲得的MD5值都是有很大的區別。

d.弱抗碰撞:已知原數據和其MD5值,想找到一個具備相同MD5值的數據(即僞造數據)是很是困難的。

e.強抗碰撞:想找到兩個不一樣的數據,使它們具備相同的MD5值,是很是困難的。

對稱加密:

須要對加密和解密使用相同密鑰的加密算法。因爲其速度快,對稱性加密一般在消息發送方須要加密大量數據時使用。對稱性加密也稱爲密鑰加密。經常使用的對稱加密算法有:DES、RC二、AES等等。

非對稱加密:

與對稱加密算法不一樣,非對稱加密算法須要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,若是用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;若是用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。由於加密和解密使用的是兩個不一樣的密鑰,因此這種算法叫做非對稱加密算法。支付寶中的加密技術就是用的非對稱加密技術。經常使用的非對稱加密算法有:RSA、ECC、D-H等等。

 

5.如何使用KVC(參考)去取得一個對象的屬性值 ,什麼是KVC、KVO、通知中心?

KVC是OC語言的一個特性,能夠對對象進行動態的讀寫操做。KVC的操做方法由 NSKeyValueCoding協議提供,而NSObject已經實現了這個協議,所以OC中的幾乎全部對象均可以使用KVC操做。

經常使用的KVC操做方法有:

(1)設置屬性值

  setValue:value forKey:key (用於簡單路徑,也就是直接屬性)

  setValue: value forKeyPath:key (用於複雜路徑,也就是間接屬性)

(2)獲取屬性值

  valueForKey: key  (用於獲取簡單路徑的屬性值)

  valueForKeyPath: key (用於獲取複雜路徑的屬性值)

KVC使用對應的函數便可設置值、得到值。那麼,KVC是如何查找一個屬性進行讀取呢?KVC遵循下面的規則,假設要對name屬性進行讀取:

(1)設置屬性:優先考慮setName方法;若是沒有,則搜索成員變量_name;若是沒找到,則搜索成員變量name;若是尚未找到,則調用 setValue: forUndefineKey: 方法。

(2)讀取屬性:優先考慮getName方法;若是沒有,則搜索成員變量_name;若是沒找到,則搜索成員變量name;若是尚未找到,則調用 valueForUndefineKey: 方法。

KVC中有一個很是重要的方法: setValuesForKeysWithDictionary:dict ,該方法能夠將一個字典映射到一個對象,省去了給對象一一賦值的步驟。

實際上,setValuesForKeyWithDictionary:dict 方法就是遍歷dict,對dict 中的每一個鍵值調用 setValue: forKey: 方法。

使用setValuesForKeyWithDictionary:dict一個須要注意的地方

當字典中有某個值,而對象沒有相應的屬性時,會發生崩潰。這時候須要使用一個方法去避免這個崩潰的發生。該方法爲: setValue: forUndefineKey: 方法

KVO:

KVO全稱 Key Value Observing。使用KVO能夠實現視圖組件和數據模型的分離,視圖做爲監聽器,當模型的屬性值發生變化後,監聽器能夠作相應的處理。KVO的方法由NSKeyValueObserving協議提供,一樣NSObject已經實現了該協議,所以幾乎全部的對象均可以使用KVO。

使用KVO操做經常使用的方法以下:

註冊制定路徑的監聽器: addObserver:  forKeyPath: option: context:

刪除制定路徑的監聽器:removeObserver: forKeyPath:

觸發監聽時的方法:observeValueForKeyPath: ofObject: change: context: 

 通知中心不作過多囉嗦:參考

說到通知中心一定要與代理進行區別:通知中心能夠:1對1;1對多;可是代理只能是:1對1的。

 

6.什麼是 Sqllite ,Sqlite 與 coreData 的區別 ?參考

 Sqlite是一種輕量級的數據庫,是一種關聯式的數據管理系統,多使用在嵌入式應用系統中,在嵌入式系統應用中佔用不多的內存(少到只有幾百k的內存),可是做用很是的重要,能夠說是 Sql Sever 的極大簡化。

CoreData 是一種數據框架,爲咱們提供了一個通用的數據管理解決方案。不管是什麼樣的程序,只要牽扯到數據管理,幾乎均可以使用到 CoreData 。蘋果的用戶面板上已經爲咱們建立了關於CoreData 的控制面板,咱們能夠很方便的去對數據庫進行遷移升級的操做。編程人員不須要寫苦逼的SQL語句,這一切蘋果都在咱們建立CoreData 應用的時候已經建立完成,將咱們的應用程序要是用的數據在內存中以數據對象模型的形式展現給系統使用。

CoreData 對於處理對象的生命週期、對象之間的關係它作了一系列的自動化的解決方案,對於數據庫的更新的時候,每次新增一個屬性字段,數據庫裏面全部的數據字段都要跟着進行一下遷移(升級),這個數據庫的升級能夠經過Xcode 的控制面板來快速的升級。(參考4對應的博文裏說的很是的好)

Core Data 爲數據變動管理、對象存儲、對象讀取恢復的功能提供了支持。 它可使用SQLite做爲持久化存儲的類型。 它自己並非一個數據庫(這點很重要,好比,你可使用Core Data來記錄數據變動,管理數據,但並不能用它向文件內存儲數據)。

CoreData 支持的4種數據類型的存儲:SQLitestore、XMLStore、BinaryStore、InMemoryStore.(這裏與 博文對比學習

下面是來自互聯網的解說。上面是本身的總結: 參考1  餐卡2  參考3  參考4

用於處理全部應用程序的數據模型需求,不論程序的規模大小。您能夠在此基礎上構建任何應用程序,從聯繫人管理程序到矢量圖演示程序。只有您想不到的,沒有什麼作不到。幾乎全部須要管理數據對象的應用程序都能獲益於 Core Data。 Interface Builder 是蘋果的圖形用戶界面編輯器,提供了預製的 Core Data 控制器對象,用於消除應用程序的用戶界面和數據模型之間的大量粘合代碼。您沒必要擔憂 SQL 語法,沒必要維護邏輯樹來跟蹤用戶行爲,也沒必要建立一個新的持久化機制。這一切都已經在您將應用程序的用戶界面鏈接到 Core Data 模型時自動完成了。 Core Data 將您的應用程序模型層組織爲一組在內存中定義好的數據對象。Core Data 跟蹤這些對象的變化,並能夠根據須要恢復這些改變,好比用戶能夠執行撤銷命令。而後,當須要保存應用程序數據對象的改變時,Core Data 負責將這些對象保存至持久性的存儲介質。並且,它會將數據保存到普通文件中,用戶能夠經過 Finder 管理這些文件、用 Spotlight 搜索這些文件、將文件備份到 CD 以及經過電子郵件將它們發送給朋友和家人。 使用Core Data 框架,您能夠建立一個託管對象模型,它爲您的應用程序所使用的模型對象,即實體提供了抽象定義。這種實體-關係模型是採用 Xcode 的「數據模型設計」工具定義的,該工具爲模型實體以及它們之間的關係提供了內容豐富的環境。它就像一套詳細的方案爲應用程序的數據類型和這些數據類型之間的關係服務。

 

7.Block的內存管理?

Block什麼都不作的話,在棧區。當在Block內部去調用全局變量或者屬性的時候在棧區。這時候須要去拷貝Block,在寫屬性的時候要用Copy,須要release,在MRC下若是在Block的內部使用了 self 就會致使對該控制器的引用計數加1,最後致使不能釋放該 Block 就會形成不能釋放的後果。有一個bloock 專門 release 的API,釋放block寫在 dealloc裏面.在 block 內調用一個對象須要使用 __Block 去修飾該對象,這是在 MRC 的狀況下。

ARC 下須要將 __Block 改成 __weak.

 

8.代理中爲何不用 weak 而用 assign?

實際上 weak 會比 assign 更好 , 由於最後 weak 會將代理置爲 nil ,可是 assign 不會這麼作,代理中在寫 assign 有的狀況下會出現崩潰,而 weak 更好些。在 MRC下會用 assign 在 ARC  下固然要用 weak.

 

9.多線程在GCD中的使用?參考

GCD是一個管理線程的線程池,如何建立、如何回收、如何分配線程,都是由 GCD 本身安排的,只須要編程人員將應該作的任務放到對應的隊列裏便可。GCD的全稱是 Grand Central Dispatch 。

GCD中有多種隊列,其中自定義隊列有兩種:串行隊列、並行隊列。不管是串行隊列仍是並行隊列,他們都是 FIFO 先進先出的。

 串行隊列:一次只可以執行一次任務的隊列,執行完一次任務以後才能執行洗一次的任務。

 並行隊列:一次能夠執行多個任務。

GCD中的操做有兩種,同步操做,異步操做。

同步操做:不會開闢新的線程。

異步操做:  會新開闢線程。

兩種操做和兩種隊列,組合爲4種狀況,實際上,在開發中,有些組合基本上是不會用到的。

組合一:串行隊列 同步操做  任務一個一個的執行,其實是順序執行

- (void)gcdDemo1

{
    //串行隊列+同步操做
    dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
    for(int i = 0; i < 10; ++i){
        dispatch_sync(queue, ^{
            NSLog(@"%@ %d",[NSThread currentThread],i);
        });
    }
}

組合二:串行隊列 異步操做   任務一個一個的執行,可是由於是異步操做,因此會開闢一個新的線程,全部的任務都會在新的線程上執行

- (void)gcdDemo1
{
dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_SERIAL);
//串行隊列+異步操做
for (int i = 0; i < 10; ++i){
dispatch_async(queue, ^{
       NSLog(@"%@ %d",[NSThread currentThread],i);
    });
  }
}

組合三:並行隊列 同步操做   並行隊列一次能夠開啓多個線程,可是是同步操做,這樣一次就只能在主線程中執行一個任務,而且是按照順序執行的。

- (void)gcdDemo2
{
dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
//並行隊列+同步任務
for(int i = 0; i < 10; ++i){
dispatch_sync(queue, ^{
  NSLog(@"%@ %d",[NSThread currentThread],i);
      });
    }
}

組合四:並行隊列 異步操做   並行隊列一次能夠開啓多個線程;異步操做能夠開啓多個線程,這樣一次可以執行多個任務,開啓多個線程,每一個任務的結束時間是不可以肯定的,而且任務也不是順序執行的。

- (void)gcdDemo2
{
dispatch_queue_t queue = dispatch_queue_create("gcddemo", DISPATCH_QUEUE_CONCURRENT);
//並行隊列+異步任務
for(int i = 0; i < 10; ++i){
dispatch_async(queue, ^{
      NSLog(@"%@ %d",[NSThread currentThread],i);
     });
   }
}

 注意:爲了開發方便,蘋果提供了全局隊列,全局隊列其實是一個並行隊列。

全局隊列 + 同步任務: 執行效果是一條一條執行,每一條執行的時候,都會開啓新的線程,在新的線程中執行任務。

- (void)gcdDemo3
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//全局隊列+同步任務
for (int i = 0; i < 10; ++i){
//同步任務
dispatch_sync(queue, ^{
NSLog(@"%@ %d",[NSThread currentThread],i);
     });
   }
}

全局隊列 + 異步任務: 執行效果是與上面的組合四是一樣的。

 - (void)gcdDemo3

{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//全局隊列+異步任務
for(int i = 0; i < 10; ++i){
dispatch_async(queue, ^{
     NSLog(@"%@ %d",[NSThread currentThread],i);
     });
   }
}

注意:蘋果還提供了一種隊列是主隊列,主隊列是串行隊列,可是與單一的串行隊列有差異,該主隊列上的任務都是在主線程中執行,即使是異步任務在主隊列上執行,系統也不會開啓新的線程。

主隊列+異步任務:

- (void)gcdDemo4
{
dispatch_queue_t queue = dispatch_get_main_queue();
//主隊列+異步任務
for(int i = 0; i < 10; ++i){
dispatch_async(queue,^{
   NSLog(@"%@ %d",[NSThread currentThread],i);
     });
   }
}

主隊列+同步任務(會阻塞線程)

- (void)gcdDemo4
{
dispatch_queue_t queue = dispatch_get_main_queue();
//主隊列+同步任務,會阻塞
for(int i = 0; i < 10; ++i){
dispatch_sync(queue, ^{
   NSLog(@"%@ %d",[NSThread currentThread],i);
     });
   }
}

主隊列中自己是有一個任務A的(主任務),且該任務A尚未執行完。在執行任務A的過程當中,又插入了新的同步任務B。咱們知道,串行隊列中,必須先執行完一個任務後,才能繼續執行另外一個任務。此時的狀況時:

若想繼續執行任務A,須要先把任務B執行完,若想繼續執行任務B,須要先把任務A執行完,所以形成了阻塞。

在開發中,應該避免這種阻塞的狀況。

 

10.如何對 UITableView  作性能優化? 參考  參考

a.使用不透明的視圖。不透明的視圖可以極大的提升渲染速度。

    若是能夠的話,將 UItableView 的 cell 以及 其子視圖的 opaque 設置爲 YES (參考)這樣設置 ios 可讓系統以最優的方式來繪製view。包括圖像的 alpha 值也要設置爲1.不要 使用這個 clearColor。

b.不要建立沒必要要的重複的 cell 。能夠設置一個重用的 cellid

static NSString *CellIdentifier = @"xxx";

UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

}

在cell 重用的時候,它的內部繪製的內容並不會被自動的清除,咱們能夠調用 setNeedsDisplay 方法。

c.儘量的減小視圖的數目

d.不要作多餘的繪製工做

e.預渲染圖像

f.不要阻塞主線程

g.也能夠設置一下,提早去加載數據,解決用戶的等待加載數據的狀況,能夠在用戶瀏覽到倒數第10條數據的時候,讓線程去加載數據。

 

11.常見的設計模式?參考1 參考2 

代理設計模式、觀察設計模式、MVC設計模式、單例設計模式、策略設計模式、工廠設計模式。

 對於單利設計模式,蘋果API中 UIAccelerometer 和 UIAppdeleagte 類都是單例類。

觀察設計模式,可讓View做爲監聽者,讓其去監聽數據模型的變化,若是數據模型的值變化,就對相應去改變監聽者的的UI。

MVC設計模式就是常常用的到的,沒啥可囉嗦了。

代理設計模式也是很是經常使用的,UIPickView 、UITableView 等等都用到了代理設計模式,傳值中也經常使用。

 

12.關於Block 的使用?參考

 

13.什麼是 MVVM設計模式? 參考

在理解MVC的設計模式基礎上,M層顧名思義,就是數據層,數據傳輸對象的封裝;V:就是展現層,就是ViewController層,他的任務就是從ViewModel層獲取數據,而後顯示;VM:就是View和Model層的粘合劑,他是一個放置用戶輸入驗證邏輯,視圖顯示邏輯,發起網絡請求和其餘各類各樣的代碼的極好的地方。說白了,就是把原來ViewController層的業務邏輯和頁面邏輯等剝離出來放到ViewModel層。

MVVM 實際上是一個 MVC 的加強版,並將表示邏輯從 Controller 移出放到一個新的對象裏,即 View Model。在 iOS 上使用 MVVM 的動機,就是讓它能減小 View Controller 的複雜性並使得表示邏輯更易於測試。

 

14.XML 與 Json 的區別?

 對於JSON數據的解析,網上一直有人說,它要代替xml,成爲網絡數據的通用格式。從 IOS 5 以後蘋果推出了原生的json 解析 API(NSJSONSerialization)。咱們依舊可使用一些第三方去解析如:SBJson、JSONKit、TouchJson。使用原生的解析類解析數據最快,JSONKit的速度次之。

XML的解析主要有:SAX 解析:基於事件的回調的解析機制,(主要區別於 DOM 解析)一行一行的解析 (缺點:效率低),適合大數據解析。系統提供好的類 NSXMLParser。.DOM 解析 : 把解析數據所有讀入內存,初始化爲樹形結構,而後再進行逐層的分析,相對於 SAX 解析,效率高,不適合大數據的讀取。通常都是採用谷歌提供的第三方類 GDataXMLNode。

XMl適合於較複雜的數據結構,而JSON 適合簡單的數據結構。前者傳輸速度較慢,後者較快。

在解析數據的時候,對於 Html 的解析要使用到 XPath ,對於數據類型爲 NSNumber 類的數據要當心,首先要作一下格式化處理。

 

15.NSURLConnection 與 NSURLSession 的區別? 參考

NSURLConnection:

NSURLConnection 是一組系統的構成 Foundation 框架中的 URL  加載系統的互相關聯的組件:NSURLRequest, NSURLResponse, NSURLProtocol , NSURLCache,NSHTTPCookieStorage,NSURLCredentialStorage,以及和它同名的 NSURLConnection。

NSURLRequest對象被傳遞給一個NSURLConnection對象。委託(遵照從前的非正式<NSURLConnectionDelegate> 和  <NSURLConnectionDataDelegate>協議)做爲一個NSURLResponse異步響應,任何相關的NSData從服務器發送。

在一個請求發送到服務器以前,首先去訪問共享的高速緩存,而後根基策略和可用性,一個緩存的響應能夠當即被返回過來,若是全部緩存的響應都不可用,則該請求根據選項,被用於爲任何後續請求緩存它的響應。

在協商發送一個請求到服務器的過程當中,該服務器可發出驗證質詢,這能夠由共享的cookie,證書存儲(credential storage)或經過鏈接委託自動處理。必要的時候,爲了無縫地改變裝載行爲,傳出請求也能夠被註冊的NSURLProtocol對象截獲。**

NSURLSession:

與NSURLConnection相似,除了同名類NSURLSession,NSURLSession也是指一組相互依賴的類。NSURLSession包括與以前相同的組件,例如NSURLRequest, NSURLCache等。NSURLSession的不一樣之處在於,它把 NSURLConnection替換爲NSURLSession, NSURLSessionConfiguration,以及3個NSURLSessionTask的子類:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask.

與NSURLConnection相比,NSURLSession最直接的改善就是提供了配置每一個會話的緩存,協議,cookie和證書政策(credential policies),甚至跨應用程序共享它們的能力。這使得框架的網絡基礎架構和部分應用程序獨立工做,而不會互相干擾。每個NSURLSession對象都是根據一個NSURLSessionConfiguration初始化的,該NSURLSessionConfiguration指定了上面提到的政策,以及一系列爲了提升移動設備性能而專門添加的新選項。

NSURLSession 的另外一個重要的組成部分是會話任務,他負責處理數據的加載,以及客戶端與服務器端之間的文件和數據的上傳和下載服務。

 NSURLSessionTask與NSURLConnection是及其類似的,由於它負責加載數據,而主要的區別在於,任務共享它們父類NSURLSession的共同委託(common delegate)。 
NSURLSessionTask是一個抽象子類,它有三個具體的子類是能夠直接使用的:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。這三個類封裝了現代應用程序的三個基本網絡任務:獲取數據,好比JSON或XML,以及上傳下載文件。

當一個NSURLSessionDataTask完成時,它具備關聯的數據,而一個NSURLSessionDownloadTask完成時,它具備一個已下載文件的臨時文件路徑。

NSURLSessionUploadTask 繼承了 NSURLSessionDataTask,由於服務器響應一個上傳請求時,每每伴隨着相關聯的數據。 全部任務都可撤銷,也能夠暫停和恢復。當一個下載任務被取消時,它能夠選擇建立恢復數據,而後能夠傳遞給下一次新建立的下載任務,以便繼續以前的下載。

 

16.什麼是 NSKeyedArchiver?

 

17.咱們在使用 XIB 和 Storyboard 的時候 有四個文件 View.xib 、 Empty.xib 、Launch Screen.storyboard、Storyboard.storyboard 他們都有什麼區別?

 XIB 與 Storyboard 的區別:二者都是用來描述軟件界面的設計,前者是輕量級的,主要用於一些局部的UI的設計,後者是重量級的,主要用於複雜頁面的設計,能夠設計模塊級別的頁面UI設計。

View.xib 與  Empty.xib 都是 XIB 輕量級的用戶界面編程組件。

Launch Screen.storyboard 與 Storyboard.storyboard 都是 Storyboard 重量級的用戶界面編程組件。

NIB 和 XIB 相同點:都是 可視化編程的圖形界面設計文檔。可視化編程 Interface Bulider 將窗口,菜單,以及窗口上的各類組件都」凍「在了一個 nib 文檔中,在程序運行的期間,這些文檔就會被激活。

NIB 和 XIB 異同點:NIB爲二進制文件,XIB是純文本文件,後者方便於咱們版本控制和對文件的比較。XIB 文件能夠被編譯成二進制文件。

 

18.在 XIB 的構成成分中有 3 個圖標,分別是什麼?具備什麼樣的功能?

File's Owner 就是全部 nib 文件中的每個圖標,標示的是從系統的磁盤讀取的文件。

First Responder 是當前用戶正在交互的交互對象。

View 是用戶用於顯示用戶交互事件的視圖,完成用戶的交互,是 UIView 類以及其之類。

 

19.關於公鑰、私鑰、數字證書的理解? 參考

20.類目與繼承的區別,在什麼狀況下使用繼承不用類目? 參考

 

21.野指針是什麼,如何理解? 參考

所謂野指針:指向一個已刪除的對象或未申請訪問受限內存區域的指針。與空指針不一樣,野指針沒法經過簡單地判斷是否爲 NULL避免,而只能經過養成良好的編程習慣來盡力減小。對野指針進行操做很容易形成程序錯誤。野指針的成因主要有兩種: (1)指針變量沒有被初始化。任何指針變量剛被建立時不會自動成爲NULL指針,它的缺省值是隨機的,它會亂指一氣。因此,指針變量在建立的同時應當被初始化,要麼將指針設置爲NULL,要麼讓它指向合法的內存。 (2)指針p被free或者delete以後,沒有置爲NULL,讓人誤覺得p是個合法的指針。別看free和delete的名字惡狠狠的(尤爲是delete),它們只是把指針所指的內存給釋放掉,但並無把指針自己幹掉。一般會用語句if (p != NULL)進行防錯處理。很遺憾,此時if語句起不到防錯做用,由於即使p不是NULL指針,它也不指向合法的內存塊。例: char *p = (char *) malloc(100); strcpy(p, 「hello」); free(p); // p 所指的內存被釋放,可是p所指的地址仍然不變 if(p != NULL) // 沒有起到防錯做用 strcpy(p, 「world」); // 出錯

相關文章
相關標籤/搜索