2

Objective-C ARC と を混在させるためのベスト プラクティスは何longjmpですか?

スクリプト言語として Lua を使用しており、私のプラットフォームはスクリプト用のカスタム ライブラリをエクスポートしています。luaL_checkinteger(L, 2)エントリポイントは(とりわけ) で引数をチェックします。これは、 /luaL_typerror(L, 2, ...)で Lua に実装されている を呼び出すことができます。私の知る限り、ARC は単純に自動生成/コードを生成しますが、範囲外の場合はどうなりますか? このコードは、引数の入力ミスでリークしますか?setjmplongjmpretainreleaselongjmp

static int
set_tag(lua_State *L)
{
    NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
    [control setTag:(NSInteger)luaL_checkinteger(L, 2)]; // may longjmp!
    return 0;
}

上記のスニペットでは、controlは ARC によって一時的に保持されますが、longjmpキャッチ不能な性質により、対応するリリース コールが発生しない可能性があります。一方、変数に代入する前に、すべての引数をチェックすることができます。control

static int
set_tag(lua_State *L)
{
    NSInteger tag = luaL_checkinteger(L, 2); // may longjmp!
    NSControl *control = (__bridge NSControl *)lua_topointer(L, 1);
    [control setTag:tag];
    return 0;
}

上記の[潜在的な]リークは解決されますか? これを行うためのより良い方法はありますか?

更新: longjmpLua の内部にのみ巻き戻し、Lua ソース (認識されている) と私のエントリ ポイント (認識されていることを願っています) を除いて、システム コードを交差させることはありません。

2 番目のスニペットが正しいと確信していますが、正式な証明が必要です。


後期更新:

LuaJIT は dwarf2 互換のエラーを実装しているため、C++ の例外と同様です。Lua コードを使用してアーク対応ソースにコンパイラ フラグを渡す-fobjc-arc-exceptionsと、保持されているオブジェクトは任意の で解放されますlua_error。今、心配することは何もありません!ただし、Cocoa ランタイム全体でエラーをスローすることはまだ許可されていません。

元の Lua も例外付きでコンパイルされている可能性があることを思い出しますが、よくわかりません。

4

2 に答える 2

1

ARC が使用されているかどうかは問題ではありません。システム フレームワークからコードの任意のフレームを飛び越えるany setjmp/は、未定義の動作を引き起こします (回復可能なエラー処理に例外を使用できないのと同じ理由で)。longjmp

そうです、そのコード漏洩する可能性があります。 コンパイラがそのブロックで /を発行するかどうかとその場所に依存するためかもしれません。また、コンパイラが/を発行するかどうかは、最適化レベルと、時間の経過とともにコンパイラのバージョンの影響を受けるためかもしれません。retainreleaseretainrelease

longjmpLua 内部に巻き戻すだけで、Lua ソース (認識されている) と私のエントリ ポイント (認識されていることを願っています) を除いて、システム コードを超えることはありません。

それは役に立ちます。システム スコープと Lua のジャンプ可能なスコープが決して混ざらないようにエントリ ポイントを構成している限り、問題はありません。これを管理する必要があるソース ファイルでは ARC をオフにすることをお勧めします (もちろん、ObjC->Lua インターフェースを適切にカプセル化された実装のビットに配置して、残りのコードを ARC クリーンにすることもできます)。

ただし、明らかでないリスクがあることを考慮してください。

for(id x in anArray) {
    ... lua call that causes longjmp ...
}

上記の場合、lua はシステム コードを「ジャンプ」します。、 KVO enumerateWithBlock:、通知ハンドラなどについても同様です...

Lua からコードへの呼び出しによって発生する可能性のあるすべてのスタック トリガーについて、非常に慎重に検討する必要があります。その呼び出しが、システムの一部で何らかの自動化された動作をトリガーし、Lua API を呼び出して をトリガーできるlongjmp場合、すべての賭けはオフになります。

于 2013-12-21T17:06:39.603 に答える
1

longjmp()ARC でクラッシュまたはリークが発生する可能性があります。longjmp()ARC が干渉しないようにコードを配置することは困難です。

致命的なエラー パスのみを対象としてlongjmp()おり、それに応じてプロセスを停止することが予想される場合は、問題を無視できる可能性があります。これは、デフォルトで ARC が C++/ObjC 例外に対して行うことです。例外がスローされると、ARC コードがリークすることが予想されます。例外のクリーンアップ コードを有効にするコンパイラ オプションがありますが、パフォーマンスが低下します。

longjmp()プロセスを強制終了するエラーでない場合は、longjmp()呼び出しによってスキップされる可能性のあるコードで ARC を無効にすることをお勧めします。

于 2013-12-23T00:41:50.623 に答える