2016-05-11 2 views
0

私は、Objective-CのClass型のargsのリストを解析したいと考えています。私は現在、リストを解析して解析するたびにEXEC_BAD_ACCESSを取得しています。リストを解析する実装を次に示します。タイプのクラスvarargsのリストを解析する

#import <Foundation/Foundation.h> 

@interface NSArray (Args) 

+ (NSArray *)arg_fromArgs:(id)clazz, ... NS_REQUIRES_NIL_TERMINATION; 

@end 

#import "NSArray+Args.h" 

@implementation NSArray (Args) 

+ (NSArray *)arg_fromArgs:(id)clazz1, ... { 
    NSMutableArray *arguments = [NSMutableArray new]; 

    id eachObject; 
    va_list argumentList; 
    if (clazz1) 
    { 
     [arguments addObject:clazz1]; 
     va_start(argumentList, clazz1); 
     while ((eachObject = va_arg(argumentList, id))) 
     { 
      [arguments addObject: eachObject]; 
     } 
     va_end(argumentList); 
    } 

    return [NSArray arrayWithArray:arguments]; 
} 

@end 

while ((eachObject = va_arg(argumentList, id)))行が不正なアクセスを取得する場所です。私はそれをどのように呼び出すのですか:

NSArray *classes = [NSArray arg_fromArgs:[Class1 class], [Class2 class], [Class3 class], nil]; 

私はid変数をClassに変更しようとしましたが、それでも何もしません。どのように私はこれを達成することができるかについてのアイデア(クラスの配列を自分のメソッドに直接渡すことを除いて)?

注:このクラッシュは物理デバイスでのみ発生します。それはシミュレータ上で完璧に動作します。事前に

おかげ

EDIT

これは、私がnewacctの提案に基づいて、それを解決する方法です。最初のクラスを通過する必要がない方法はありますか?

+ (NSArray *)arg_fromClass:(Class)clazz andArgsList:(va_list)argumentList { 
    NSMutableArray *arguments = [NSMutableArray new]; 
    [arguments addObject:clazz]; 

    id eachObject; 
    while ((eachObject = va_arg(argumentList, id))) 
    { 
     [arguments addObject: eachObject]; 
    } 
    va_end(argumentList); 

    return [NSArray arrayWithArray:arguments]; 
} 

私はそれをどのように呼びますか。私はあなたが投稿したサンプルアプリケーションを見てきました

- (void)someMethod:(Class)clazz, ... { 
    va_list argumentList; 
    va_start(argumentList, clazz); 
    NSArray *classesToSync = [NSArray arg_fromClass:clazz andArgsList:argumentList]; 

    NSLog(@"Syncing Classes: %@", classesToSync); 
} 

おかげ

+0

私はあなたがシミュレータ上でこれを実行しています@newacctクラッシュ – newacct

+0

を再現することはできませんがあり、例えば、CのAPIでこれを見ることができますか?私は、クラッシュが物理的なデバイスでのみ発生することに言及することを忘れました。 – DMCApps

+0

まだ再生できません。自己完結型のサンプルプログラムを提供してください。 – newacct

答えて

1

+[NSArray arg_fromClassArgs:]メソッドに問題はありません。これは、最後にnil引数を持つオブジェクトポインタ引数の可変数を期待するvarargsメソッドです。

問題は、あなたの+[ArgReceiver convertArgsToArray:]方法で、このように、このメソッドを呼び出すことです:

[NSArray arg_fromClassArgs:args] 

あなたは終わりがないnil引数を指定して、一つの引数を渡します。

そして、あなたの +[ArgReceiver convertArgsToArray:]方法が書かれている方法は、変数引数を「オフ渡す」ことを意図していることを示しているようだ(それ自体は、可変個の引数を取る可変引数メソッド、あなたが argsに名前を付けたの初めてです)そのメソッドから別のvarargsメソッドに変更します。しかし、それは不可能です。Cでは、varargs関数がその引数を別のvarargs関数に渡す標準的な方法はありません。

単一va_list引数(多分+[NSArray arg_fromClassArgsVaList:]か何かそれを呼び出す)、他の可変引数メソッドを呼ぶために(そしてどの+[NSArray arg_fromClassArgs:]自身が呼び出すことができますを取る+[NSArray arg_fromClassArgs:]方法の別のバージョンを持っているだろう唯一の方法なので、あなたのドンコードが重複しています)。あなたはprintf等、vprintfあり、そしてココアで、-[NSString initWithFormat:]-[NSString initWithFormat:arguments:]

+0

ああ、意味があります。一方、物理デバイス上ではなく、シミュレータ上で正常に動作する理由について、どんな傾向がありますか?私はそれがプロセッサの違いと関係していると推測しています、そして、彼らはそれぞれ命令をどのように扱いますか?もう少し混乱しているのは、コードをデバッグすると、 '[NSArray arg_fromClassArgs:]'に入り、まだ4回ループしています(ここに何か他のものがない限り、nil終了時にクラッシュします)。 – DMCApps

+0

@DMCApps:それは私のためにもシミュレータでクラッシュします。とにかく、それは未定義の振る舞いであり、その理由は何もありません。渡されたよりも多くの引数を読み込もうとすると、おそらくオブジェクトの有効なポインタを持つ可能性があります。 – newacct

+0

これを正しくマークしましたが、解決方法が不明な問題が1つあります。私のva_listは渡されたパラメータの最初の項目を持っていません。私は間違ったことをしていますか?私は今どのように解決しているのかをコードを更新しましたが、他に何か不足していますか? – DMCApps

関連する問題