iOS開發 乙個iOS覆蓋面比較廣面試題

2021-10-03 07:54:16 字數 4632 閱讀 5399

結尾在@property (nonatomic, strong) nsstring *name;的情況下分別執行以下兩段**,會發生什麼?

//code 1

dispatch_queue_t queue =

dispatch_get_global_queue(0

,0);

for(

int i =

0; i <

1000

; i++))

;}//code 2

dispatch_queue_t queue =

dispatch_get_global_queue(0

,0);

for(

int i =

0; i <

1000

; i++))

;}

這裡涉及的知識點有

多執行緒安全

屬性修飾詞的定義nonautomic自動釋放池autoreleasepoolruntime執行時機制,以及nstagged pointermrc下的set方法寫法

結果是code 1會發生崩潰,code 2不會

崩潰資訊如下

* thread #3

, queue =

, stop reason = exc_bad_access (code=exc_i386_gpflt)

* frame #0

:0x000000011077f01b libobjc.a.dylib`objc_release +

11 frame #1

:0x00000001107804c7 libobjc.a.dylib`(anonymous namespace)

::autoreleasepoolpage:

:pop

(void*)

+795

frame #2

:0x000000011328d5eb libdispatch.dylib`_dispatch_last_resort_autorelease_pool_pop +

27 frame #3

:0x000000011329e4cc libdispatch.dylib`_dispatch_root_queue_drain +

1569

frame #4

:0x000000011329e9af libdispatch.dylib`_dispatch_worker_thread2 +

130 frame #5

:0x0000000113679169 libsystem_pthread.dylib`_pthread_wqthread +

1387

frame #6

:0x0000000113678be9 libsystem_pthread.dylib`start_wqthread +

13

下面分析原因:

由於是nonatomic,即表示非原子setget方法在多執行緒中不再安全,當然atomic也無法完全保證其在多執行緒中讀寫的資料安全,atomic只會保護setget方法,這裡不再詳細闡述。

不安全在**呢?由於set方法是這樣的,在mrc下(mrc下**用於分析)

-

(void

)setname:

(nsstring *

)name

}//當多執行緒中多個執行緒同時執行這個方法時,有可能出現重複呼叫`release`的情況

//即某乙個時刻,_name的位址還未變化前提下,[_name release]; 呼叫了兩次

dispatch_async(queue, ^);這個方法只是代表在佇列queue非同步執行,不能保證其執行緒唯一性,你可以列印執行緒資訊來證實,即可能在多個執行緒中執行(從執行緒池中取),所以存在多執行緒問題。

dispatch_async(queue, ^);會將建立的變數加入到自動釋放池中,**其實就相當於這樣

//code 1

dispatch_queue_t queue =

dispatch_get_global_queue(0

,0);

for(

int i =

0; i <

1000

; i++))

;}

崩潰的原因,當某一時刻變數從autoreleasepoolpop時,會呼叫objc_release()方法將其釋放(參考文章),此時可能存在_name變數重複釋放,已經是壞記憶體了,從而崩潰。

也可以認為是多個執行緒執行了[_name release];導致了崩潰。

//code 2

dispatch_queue_t queue =

dispatch_get_global_queue(0

,0);

for(

int i =

0; i <

1000

; i++))

;}

[nsstring stringwithformat:@"abc"];是相對於生成了乙個nstagged pointer,見參考文章 末尾有說明,由runtime知識,objc_msgsend內部會判斷是不是普通的指標,如果使用了tagged pointer技術,就不是乙個oc物件,會從指標中直接進行取值,而不會進入訊息機制,做相應的記憶體管理**的呼叫.

object_msgsend的彙編**中,我們常常會看到tagged point型別的判斷,如下段**

end_entry _objc_msgsend

entry _objc_msglookup

unwind _objc_msglookup, noframe

cmp x0, #0

// nil check and tagged pointer check

b.le llookup_nilortagged // (msb tagged pointer looks negative)

ldr x13,

[x0]

// x13 = isa

and x16, x13, #isa_mask // x16 = class

llookup_getisadone:

cachelookup lookup // returns imp

llookup_nilortagged:

b.eq llookup_nil // nil check

// tagged

mov x10, #0xf000000000000000

cmp x0, x10

b.hs llookup_exttag

adrp x10, _objc_debug_taggedpointer_classes@page

add x10, x10, _objc_debug_taggedpointer_classes@pageoff

ubfx x11, x0, #60

, #4

ldr x16,

[x10, x11, lsl #3

] b llookup_getisadone

llookup_exttag:

adrp x10, _objc_debug_taggedpointer_ext_classes@page

add x10, x10, _objc_debug_taggedpointer_ext_classes@pageoff

ubfx x11, x0, #52

, #8

ldr x16,

[x10, x11, lsl #3

] b llookup_getisadone

_objc_debug_taggedpointer_classes實現如下

.globl _objc_debug_taggedpointer_classes

_objc_debug_taggedpointer_classes:

.fill 16,8

,0.globl _objc_debug_taggedpointer_ext_classes

既然不會走set方法,那麼就不會涉及多執行緒安全問題。

將屬性修飾改為automic或者對賦值操作加鎖,都是解決多執行緒下安全問題的方案之一。

記性不好是硬傷,所以我決定記下來,寫寫寫!

IOS開發 我的第乙個IOS程式

學完前面的objc基礎,那麼接下來我可以開始我的ios開發之旅了 1.首先開啟xcode建立乙個工程 3.在專案檔案區選擇viewcontroller.xib檔案 再選擇子螢幕object下的view,這樣就能開啟我們的iphone的窗體介面 4.接著在xcode主介面右下方拉入label butt...

iOS應用開發入門(1) 第乙個iOS應用

最近因為工作的原因,需要學習ios應用開發。本人現在在公司負責的是智慧型裝置聯網模組,所謂的智慧型裝置聯網,就是讓一些智慧型裝置 多半是沒用螢幕的裝置 連上wifi,因為沒有螢幕,所以無法像手機和平板那樣通過螢幕選擇wifi和輸入wifi密碼,這個時候就需要手機來輔助,將手機上的wifi資訊同步到智...

培養iOS開發新人的乙個思路

堅持兩個方 1 發現問題的方法 熟悉 的過程 1 照著乙個完整的工程,從最基本的頁面開始做起。不懂的地方就問,就查。2 在閱讀 或拿到需求後要學會對問題進行分解。乙個陌生的問題如果不能被分解,那麼它也很難被解決。3 根據分解出來的小任務,使用方法2進行解決。2 解決問題的方法 1 發現問題 一般是x...