2011-12-17 14 views
2

私は加速度計(毎秒20サンプル)から読み込み、タイマーを使用して5秒ごとにこれらのデータを取り込み、計算します。 加速度計データはプロパティであるNSMutableArray(加速度)に保存されます。次に、タイマーがトリガされると、この配列はセマフォを使用して新しいものにコピーされます(計算が完了している間に新しいデータを保存するため)。ブロックからの@autoreleasepoolのEXC_BAD_ACCESS

main.mの@autoreleasepool返信文にEXC_BAD_ACCESSが表示されます(変更はありません)。私はこのエラーは、私はアプリを実行するたびに同じ瞬間ではありません:それはタイマーブロックの実行のいずれかに表示されますが、特定の時間(時には2回目、時には5回目など)には表示されません非常に困惑した。
私はそれを解決するために数日間メモリ管理について調べて読んでいますが、私はそれをしません。ブロックに変数を使うのは間違いだと思いますが、わかりません。

誰かが被写体にどんな光を当てても大変感謝しています。

関連するコードはここにある:

/** 
* Function to create the timer 
**/ 
dispatch_source_t creaTimer(uint64_t interval,uint64_t leeway, dispatch_queue_t queue,dispatch_block_t block){ 
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0,queue);  
if (timer) { 
    dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway); 
    dispatch_source_set_event_handler(timer, block); 
} 
return timer; 
} 


/** 
* IBAction which executes when an "Start" button is tapped 
**/ 

-(IBAction) rec{ 

semaforoArrays = dispatch_semaphore_create(1); //creates semaphore to accessing the saved accelerometer data 

__block double *modulos; 
modulos = (double *) malloc(512);  

__block DOUBLE_COMPLEX_SPLIT A; 

/* Allocate memory for the input operands and check its availability, 
* use the vector version to get 16-byte alignment. */ 
A.realp = (double *) malloc(1024 * sizeof(double)); 
A.imagp = (double *) malloc(1024 * sizeof(double)); 

if (A.realp == NULL || A.imagp == NULL) { 
    printf("\nmalloc failed to allocate memory for the real FFT" 
      "section of the sample.\n"); 
    exit(0); 
} 

timer = creaTimer(5ull * NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0) 
        ,^{ 
    if(numCiclos>0){ 

    dispatch_semaphore_wait(semaforoArrays, DISPATCH_TIME_FOREVER); 

     NSMutableArray *originalArray= [NSMutableArray arrayWithArray: 
     self.aceleraciones]; //copy the saved data to manipulate them 
     [self.aceleraciones removeAllObjects]; //remove the saved data to put into the array the new data accelerometer will have        

    dispatch_semaphore_signal(semaforoArrays); 


    int tamanno=[originalArray count]; 

    for(int h=0;h<1024;h++){ 
     A.realp[h]=0; 
     A.imagp[h]=0; 
    } //i reuse the same array (to avoiding allocating it each time)        

    for(int r=0;r<tamanno;r++){ 
     A.realp[r]=[[originalArray objectAtIndex:r]doubleValue]; 
    } //i do that to calculate the Fourier Transform but it doesn´t 
     matter in the error (i get it also with this code). 

    vDSP_zvabsD(&A, 1, modulos, 1, 512);   
    vDSP_vsqD(modulos,1,modulos,1,512); 

    double sum=0; 

    vDSP_sveD(modulos, 1, &sum, 512); 

    sum=sum/2.0; 
    vDSP_vsdivD(modulos, 1, &sum, modulos, 1, 512); 
    } 
     numCiclos++;//variable to avoid the execution of the block the first time timer triggers (when it is started) 
});  

//until here is the problematic block. I'm sure the error is before this line. 



NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; 
if (motionManager.accelerometerAvailable) { 

    motionManager.accelerometerUpdateInterval = 1.0/20.0; 
    label.text = [NSString stringWithFormat:@"Registrando"]; 

    [motionManager startAccelerometerUpdatesToQueue:queue withHandler: 
    ^(CMAccelerometerData *accelerometerData, NSError *error){ 

     if (error) { 
      [motionManager stopAccelerometerUpdates]; 
      label.text = [NSString stringWithFormat: 
          @"Error en el acelerometro: %@", error]; 
     } 
     else{ 
      if(primeraLectura){ 
       primeraLectura = FALSE; 
       dispatch_resume(timer); //starts timer    
      } 

      dispatch_semaphore_wait(semaforoArrays, DISPATCH_TIME_FOREVER); 
      [self.aceleraciones addObject:[NSNumber numberWithDouble: 
     sqrt(accelerometerData.acceleration.x*accelerometerData.acceleration.x+ 
     accelerometerData.acceleration.y*accelerometerData.acceleration.y+ 
     accelerometerData.acceleration.z*accelerometerData.acceleration.z)]]; 
     //it saves the acceleration module 

      dispatch_semaphore_signal(semaforoArrays);   
     } 
    }]; 
}else{ 
    label.text = @"Este dispositivo no tiene acelerometro."; 
} 
} 
+0

手動保持/解放またはARCを使用していますか?前者の場合は、間違いなく何かをリリースしてはいけません。何でもかまいません - あなたが最近変更したコードに必ずしもあるとは限りません。 –

+0

@ホットリック私は手動メモリ管理を使用していますが、ブロック内の計算に関する行を削除しても、実行時に問題はありません。 – angeleke

+0

昨日、私はすべてのリファレンスでオブジェクトを再作成するのをやめ、代わりにキャッシュしました。これはあなたが見ているのとまったく同じエラーを引き起こしました。しかし、バグ(私が最終的にそれを見つけたとき)は、私の変更のどれにもなく、オブジェクトを埋め込むコードにありました.1つのアイテムが過剰にリリースされました。以前は、オブジェクトはバグが公開されるのに十分長くは住んでいなかった。 –

答えて

2

motionManager startAccelerometerUpdatesToQueue:でご覧ください。あなたはqueueパラメータをそのプロパティに保存してから、deallocでリリースする可能性があります。しかし、queueの値をプロパティに入れたときは、それを保持しませんでした。

+0

はい、私がここで知る限り、キュー変数はここで最も蓋然性が高いです。奇妙なことは、NSOperationQueuesをオートリリースするときに起き始めます。それらを実行しますが、インスタンス変数として保持しないでください。 –

+0

問題(今度は)は自動リリースしませんでしたが、一般的なルールとして、関数から返されたオブジェクトを解放するためにautoreleaseを使うべきですか? – angeleke

+0

通常は、保持されている値を返して、あなたの関数が「特別な」もの(new ...、alloc ...、copy ...など)の1つではない場合にのみ、autoreleaseを使用します保持されている値を返すことになっています。おそらく他のケースでは、オートレリースが良い効果を発揮するかもしれませんが、それは例外です。 –

3

これらのエラーをデバッグする最良の方法は、Instrumentsにあります。 Zombieプロファイルを使用して実行すると、不正なアクセスを引き起こすコードを実行すると、ポップアップウィンドウが表示されます。右下の矢印をクリックすると、alloc/deallocリストが表示され、違反コードが1行表示されます。

+0

それは素晴らしいね。ゾンビプロファイルを使用して実行するにはどうすればよいですか? –

+0

iOS 6以降、自動参照カウント(ARC)が有効になっているため、手動で保持/解放する必要はありません。そして、あなたはEXC_BAD_ACCESSを取得すべきではありません。 ARCを使用してアプリケーションを再構築することを強くお勧めします。あなたが本当に必要な場合は、インストゥルメントを実行すると、あなたが望むプロフィールのアイコンがたくさんある画面が表示されます。ゾンビもその1つです。 –

+0

私はもっと時間があれば、私は自分のアプリを再構築するでしょう。 1000行のコードごとにどれくらいの時間がかかると推定されますか? –