[英]What's the quickest way to force an iOS app to crash?
我正在嘗試測試我的崩潰分析。 我沒有意識到隨意讓應用程序崩潰是多么困難。 中間編程似乎如此簡單。 有人對我如何強制我的應用程序崩潰有任何建議嗎? 我的意思不是一點“內存錯誤”崩潰,我的意思是手機不知道如何處理自己。 我需要它至少在 Xcode 的管理器中作為崩潰進入設備日志。 有什么建議?
@throw NSInternalInconsistencyException;
殺死應用程序的方法有很多! 這是兩個合一的襯墊:
[self performSelector:@selector(die_die)];
還
@[][666];
只需寫assert(NO)
。 這會檢查作為參數給出的條件,如果為 false,則應用程序崩潰。
編輯:
exit(0)
也能解決問題
int* p = 0;
*p = 0;
給出一個EXC_BAD_ACCESS (code=2, address=0x0)
編輯:
在 Greg Parkers 評論說允許編譯器優化掉上述語句之后,這讓我更徹底地思考了上述語句,以及為什么 Greg Parker 是對的:
事實上,在 C 和 C++ 中取消引用 NULL 指針是“未定義行為”(另請參見 C99 §6.5.3.2/4)。
這意味着,上述語句的效果取決於編譯器。 這種“未定義的行為”也意味着允許編譯器應用一些優化,這可能會導致上述語句被“優化掉”——正如 Greg Parker 斷言的那樣。
好吧,現在這讓我很好奇 clang 實際上會做什么:
這是小測試程序:
int main(int argc, const char * argv[])
{
int* p = 0;
*p = 0;
return 0;
}
優化設置為“-Ofast”,我們得到這個反匯編:
0x100000f90: pushq %rbp
0x100000f91: movq %rsp, %rbp
0x100000f94: ud2
其中ud2
是一個操作碼,意思是“未定義的操作碼”並導致 CPU 異常:
`EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)`
(也許@GregParker 可以評論為什么 clang 選擇這種方法?)
雖然這很有趣,但它僅指“取消引用 NULL 指針”。 如果我們有這個:
int* p = (int*)1;
*p = 0;
程序按預期崩潰 - 但需要硬件拒絕寫入此(無效)地址的“先決條件”。
我認為好的舊數組索引超出范圍是“成功崩潰”的保證,所以這里是我最喜歡的列表:
斯威夫特 4 :
[][0]
fatalError()
目標-C :
@[][0];
int *x = nil; *x = 0;
雖然@throw NSInternalInconsistencyException;
解決您的問題,是一個異常(不是崩潰),因此可能會被捕獲。
我經常發現讓應用程序啟動,做一些事情,然后在 10 秒后崩潰很有用。 在這種情況下(對於Objective-C ),我使用:
[self performSelector:NSSelectorFromString(@"crashme:") withObject:nil afterDelay:10];
這樣做的第二個好處是編譯器不會拋出任何關於未找到選擇器的警告(如果使用 Objective-C)。 :)
斯威夫特:
self.perform("crashme:", with: nil, afterDelay: 10)
一種更可控的方法是自己實際拋出異常:
@throw [NSException exceptionWithName:NSGenericException reason:@"" userInfo:nil];
檢查NSException.h
以獲取更多異常。
對於 swift 這些對我有用:
assert(false, "sdf")
和這個:
var hey:[Int] = []
hey[0] = 1
用assert()
強制你的程序崩潰
Swift 允許您使用assert()
函數強制應用程序崩潰。 這需要兩個參數:要檢查的條件,以及斷言失敗時要打印的消息。 有用的是,當您的應用程序在發布模式下編譯時(即針對 App Store),對assert()
任何調用都會被忽略,這意味着這些檢查對您的代碼的最終性能沒有影響。
以下是使用assert()
兩個示例:
assert(1 == 2, "Maths failure!")
使用fatalError()
強制崩潰
Swift 有一個叫做fatalError()
的內置函數,它會強制你的應用程序崩潰。 這聽起來可能很有用,但請耐心等待——對於任何認真編寫優秀 Swift 的人來說,這是必不可少的功能。
fatalError(
) 函數有一個特殊的返回類型,叫做 Never,Swift 理解這意味着在這個函數被調用后,執行將永遠不會繼續。 因此,您可以在返回值的方法中使用fatalError()
,但您沒有任何可返回的值。
幸運的是, fatalError()
可以解決這個問題:如果你的類型轉換失敗,你可以調用fatalError()
並顯示一條解釋發生了什么的消息,如果類型轉換失敗,你的應用程序將終止
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? MyCustomCell else {
fatalError("Failed to load a MyCustomCell from the table.")
}
return cell
}
*(long*)0 = 0xDEADBEEF;
給出 EXC_BAD_ACCESS
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.