呼び出しobjc_msgSend法による64ビットでのクラッシュ解決法
2635 ワード
これまで64ビット以外のマシンですべての正常なプログラムをテストしていたが、iPhone 5 sで理由もなく崩壊した.クラッシュの場所はobjc_を呼び出すことですmsgSendで表示されます.苦労して検索した結果、アップルの公式サイトにはこのような記述があることが分かった.
Dispatch Objective-C Messages Using the Method Function’s Prototype
An exception to the casting rule described above is when you are calling the
Listing 2-14 shows the proper form for dispatching a message to an object using the low-level message functions. In this example, the
Listing 2-14 Using a cast to call the Objective-C message sending functions
objcを直接使うことはできないということらしいです.msgSendのプロトタイプメソッドは匿名で呼び出されます.そうしないと異常が発生します.結局上記の方法を強制的に一定の方法に変換してみたところ、再運転はクラッシュせず、Luck!!
原文:https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html
補足説明(2015-8-5):
構造体を返す方法についてobjc_を使用するとmsgSendが呼び出すと異常EXCが放出されますBAD_ACCESS:
このようなやり方では、クラッシュの問題が発生する可能性があります(ただし、プログラムごとに必ず発生するとは限りません)、公式ドキュメントを見てみると、objc_msgSendには拡張バージョンobjc_がありますmsgSend_stretは、戻り構造体の処理に特化しているため、コードを以下のように変更すれば問題を解決できます.
注意:この調整はarmv 7アーキテクチャでのみ必要であり、arm 64が含まれている場合は必要ありません.
Dispatch Objective-C Messages Using the Method Function’s Prototype
An exception to the casting rule described above is when you are calling the
objc_msgSend
function or any other similar functions in the Objective-C runtime that send messages. Although the prototype for the message functions has a variadic form, the method function that is called by the Objective-C runtime does not share the same prototype. The Objective-C runtime directly dispatches to the function that implements the method, so the calling conventions are mismatched, as described previously. Therefore you must cast the objc_msgSend
function to a prototype that matches the method function being called. Listing 2-14 shows the proper form for dispatching a message to an object using the low-level message functions. In this example, the
doSomething:
method takes a single parameter and does not have a variadic form. It casts the objc_msgSend
function using the prototype of the method function. Note that a method function always takes an id
variable and a selector as its first two parameters. After the objc_msgSend
function is cast to a function pointer, the call is dispatched through that same function pointer. Listing 2-14 Using a cast to call the Objective-C message sending functions
- (int) doSomething:(int) x { ... }
- (void) doSomethingElse {
int (*action)(id, SEL, int) = (int (*)(id, SEL, int)) objc_msgSend;
action(self, @selector(doSomething:), 0);
}
objcを直接使うことはできないということらしいです.msgSendのプロトタイプメソッドは匿名で呼び出されます.そうしないと異常が発生します.結局上記の方法を強制的に一定の方法に変換してみたところ、再運転はクラッシュせず、Luck!!
原文:https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaTouch64BitGuide/ConvertingYourAppto64-Bit/ConvertingYourAppto64-Bit.html
補足説明(2015-8-5):
構造体を返す方法についてobjc_を使用するとmsgSendが呼び出すと異常EXCが放出されますBAD_ACCESS:
CGSize (*action)(id, SEL, int) = (CGSize (*)(id, SEL, int)) objc_msgSend;
CGSize size = action(self, @selector(doSomething:), 0);
このようなやり方では、クラッシュの問題が発生する可能性があります(ただし、プログラムごとに必ず発生するとは限りません)、公式ドキュメントを見てみると、objc_msgSendには拡張バージョンobjc_がありますmsgSend_stretは、戻り構造体の処理に特化しているため、コードを以下のように変更すれば問題を解決できます.
CGSize (*action)(id, SEL, int) = (CGSize (*)(id, SEL, int)) objc_msgSend_stret;
CGSize size = action(self, @selector(doSomething:), 0);
注意:この調整はarmv 7アーキテクチャでのみ必要であり、arm 64が含まれている場合は必要ありません.