2011-07-21 7 views
4

のリリース構成でループ「のための」無限の私は自分のアプリケーションで次のコードを持っている:は、iPhoneアプリ

NSArray *lstAttributes = [conditionAttribute componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator], 
    *lstValues = [conditionValue componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator], 
    *lstValueTypes = [conditionValueType componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator]; 

if([lstAttributes count] != [lstValues count] || 
    [lstAttributes count] != [lstValueTypes count]) return NO; 

BOOL bResult = YES; 
NSLog(@"attributes amount - %u", [lstAttributes count]); 
for(uint i = 0; i < [lstAttributes count]; i ++) 
{ 
    NSLog(@"counter: %u", i); 
    SystemUIConfigurationAttributeCondition *condition = [SystemUIConfigurationAttributeCondition new]; 

    condition.conditionAttribute = [lstAttributes objectAtIndex:i]; 
    condition.conditionValue = [lstValues objectAtIndex:i]; 
    condition.conditionValueType = [lstValueTypes objectAtIndex:i]; 

    bResult &= [self checkCondition:condition forOwner:owner]; 

    FreeObject(&condition); 

    if(!bResult) break; 
} 

return bResult; 

すべてが「デバッグ」の構成で結構です。しかし、一度それを "リリース"に切り替えると、私は無限ループに直面します。コンソールは私に、属性量-2、カウンタ0、カウンタ1、カウンタ1、カウンタ1、カウンタ1、カウンタ1、カウンタ1、......などを表示します。

私は異なる "for"と "while"演算子を使いこなそうとしましたが、何も正しく動作しませんでした。ループはまだ停止できません。

誰も以前に同じ問題に直面していますか?

+0

私は客観的に奇妙なものがありましたが、それほど奇妙なものはありませんでした。私は、ループ内のすべての操作の後にiの値をトレースすることを提案することができます。したがって、ループ内のどこかで0にディクリメント/リセットされるかどうかを確認してください。そうでない場合は、for()ステートメント自体で奇妙です。 – iandotkelly

+0

これをコメントアウトしてみてください。 bResult&= [self checkCondition:condition forOwner:owner]; –

+0

あなたは試しましたか? 'for(int i = 0; i <[lstAttributes count]; i ++)... ' –

答えて

1

回避策:

最初に私の代わりにループ「のために」のリスト内のすべてのオブジェクトを列挙するためにコードブロックを使用しようとしました。

__block BOOL bResult = YES; 
[lstAttributes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
{ 
    SystemUIConfigurationAttributeCondition *condition = [SystemUIConfigurationAttributeCondition new]; 

    condition.conditionAttribute = [lstAttributes objectAtIndex:idx]; 
    condition.conditionValue = [lstValues objectAtIndex:idx]; 
    condition.conditionValueType = [lstValueTypes objectAtIndex:idx]; 

    bResult &= [self checkCondition:condition forOwner:owner]; 

    FreeObject(&condition); 

    if(!bResult) *stop = YES; 
}]; 

しかし、私は2回目の繰り返しでクラッシュしました。 "lstValues"と "lstValueTypes"ポインタが突然値を変更し、アプリケーションがEXC_BAD_ACCESSを受信しました。おそらく3つの配列を使用していて、そのうちの1つだけを列挙することは良い考えではありません。デバッガは列挙が同じスレッドで実行されることを示していますが、2つ目の反復の瞬間までに3つの配列のうち2つが壊れています。

ので、私は2つの部分に私の最初のループを分割することを決めた:

  1. 条件
  2. のリストを作成し、各条件をご確認ください。

第一、第二のループ、 "ため" が通常である - 「enumerateObjectsUsingBlock:。。」にNSArrayクラスのメソッド最後のコードは次のようになりますので:

NSArray *lstAttributes = [conditionAttribute componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator], 
    *lstValues = [conditionValue componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator], 
    *lstValueTypes = [conditionValueType componentsSeparatedByString:cstrSystemUIConfigurationAttributeConditionSeparator]; 

if([lstAttributes count] != [lstValues count] || 
    [lstAttributes count] != [lstValueTypes count]) return NO; 

NSMutableArray *lstConditions = [NSMutableArray new]; 
for(uint i = 0; i < [lstAttributes count]; i ++) 
{ 
    SystemUIConfigurationAttributeCondition *condition = [SystemUIConfigurationAttributeCondition new]; 

    condition.conditionAttribute = [lstAttributes objectAtIndex:i]; 
    condition.conditionValue = [lstValues objectAtIndex:i]; 
    condition.conditionValueType = [lstValueTypes objectAtIndex:i]; 

    [lstConditions addObject:condition]; 
    FreeObject(&condition); 
} 

__block BOOL bResult = YES; 
[lstConditions enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL *stop) 
{ 
    if([self checkCondition:[lstConditions objectAtIndex:i] forOwner:owner] == NO) 
    { 
     bResult = NO; 
     *stop = YES; 
    } 
}]; 

FreeObject(&lstConditions); 

return bResult; 

このコードは動作します

Iだろう誰かが私の初期ループの動作を説明することができれば感謝します。

0

あなたはそれはあなたが& =操作をコメントアウトした場合、私はその行を変更したい動作することをあなたのコメントに言及しているので:

bResult = bResult && [self checkCondition:condition forOwner:owner]; 

これは、あなたが本当にするつもり何ですブールのANDを行いますとにかくこの行にしてください。 & =ビット単位のANDを行います。これは、ブール値ANDと常に同じではないため、0以外の値がtrueと評価されるためです。たとえば、次のように

BOOL a = 1; 
BOOL b = 2; 

if (a && b) { 
    NSLog (@"a && b is true"); // This line will execute 
} 
if (a & b) { 
    NSLog (@"a & b is true"); // This line won't execute 
} 

それはビット単位のANDブールの代わりにを使用して、私たちの条件式の中でオブジェクトのアドレスを使用するのが一般的だし、バグを作成することができますので。たとえば、オブジェクトアドレスがgetCondition:fromOwner:から返され、YESを意味し、そのメモリアドレスが偶数である場合、YESのビット単位のANDはNOと評価され、ブール値ANDはYESと評価されます。

あなたの特定のバグの原因は、bitwise-ANDがどうにかしてバッファオーバーランを引き起こしていることです。これはあなたのi変数を突き詰めます。その仮説が正しい場合、ブール値に切り替えると、それも修正する必要があります。約束通り、このバグの

+0

あなたは正しいです、そして、私はそのようなバグに直面しました。しかし、現在のところ、この問題には問題はありません。私はそのコードが&=演算なしで動作すると書いた直後に試しました。 – alfared

+0

待って、私は混乱しています。あなたは "私が行 'bResult&= [self checkCondition:条件forOwner:owner];をコメントアウトすると"それから... "私は、その行があなたの無限ループを修正することをコメントアウトしていることを意味しました。ですから、&&の代わりに&&を使用するように行を変更すると、無限ループが修正される可能性があります。あなたは&&を使ってみたが、あなたはまだ無限ループをしていると言っていますか? – cduhn

+0

はい、私はまだ無限ループを持っています。私はどちらかを意味する "bResult&= [self checkCondition:condition forOwner:owner];" または bResult = bResult && [self checkCondition:条件forOwner:所有者]; – alfared