EXC_BAD_ACCESS sinyali alındı


290

Uygulamayı cihaza dağıtırken, program aşağıdaki hatayla birkaç döngüden sonra kapanacaktır:

Program received signal: "EXC_BAD_ACCESS".

Program iPhone simülatöründe herhangi bir sorun yaşamadan çalışır, aynı zamanda hata ayıklama ve talimatları tek tek adım attığım sürece çalışır. Tekrar çalışmasına izin verir vermez EXC_BAD_ACCESSsinyale çarpacağım .

Bu özel durumda, ivmeölçer kodunda bir hata oldu. Simülatörde çalışmaz, bu yüzden herhangi bir hata atmadı. Ancak, aygıta dağıtıldıktan sonra yürütülür.

Bu sorunun yanıtlarının çoğu genel EXC_BAD_ACCESShatayla ilgilidir, bu yüzden bunu korkunç Kötü Erişim hatası için bir catch-all olarak açık bırakacağım.

EXC_BAD_ACCESSnormalde geçersiz bir bellek erişiminin sonucu olarak atılır. Aşağıdaki cevaplarda daha fazla bilgi bulabilirsiniz.

Daha EXC_BAD_ACCESSönce sinyalle karşılaştınız ve bununla nasıl başa çıktınız ?

Yanıtlar:


196

Açıklamanızdan en olası açıklamanın bellek yönetiminizde bir hata olduğundan şüpheleniyorum. Birkaç hafta boyunca iPhone geliştirme üzerinde çalıştığınızı söylediniz, ancak genel olarak Objective C ile deneyimli olup olmadığınızı söylemediniz. Başka bir arka plandan geldiyseniz, bellek yönetimi kurallarını gerçekten içselleştirmeniz biraz zaman alabilir - büyük bir noktaya değinmediğiniz sürece.

Unutmayın, bir ayırma işlevinden (genellikle statik ayırma yöntemi, ancak birkaç tane daha vardır) veya bir kopyalama yönteminden aldığınız her şey, belleğe de sahipsiniz ve işiniz bittiğinde onu serbest bırakmanız gerekir.

Ancak, fabrika yöntemleri de dahil olmak üzere hemen hemen her şeyden bir şey alırsanız (ör.[NSString stringWithFormat] ) alırsanız, otomatik yayın referansına sahip olursunuz, bu da gelecekte başka bir kodla bir süre sonra yayınlanabileceği anlamına gelir. onu tuttuğunuz hemen fonksiyonun ötesinde tutmak için. Bunu yapmazsanız, bellek kullanılırken ayrılmış olarak kalabilir veya serbest bırakılabilir, ancak öykünücü testiniz sırasında tesadüfen hala geçerli olur, ancak cihazda çalışırken serbest bırakılması ve kötü erişim hataları olarak ortaya çıkması daha olasıdır.

Bu şeyleri izlemenin en iyi yolu ve yine de iyi bir fikir (belirgin bir sorun olmasa bile), uygulamayı Aletler aracında, özellikle Sızıntılar seçeneğiyle çalıştırmaktır.


2
Kaldırma işleminden sonra kötü erişim hatasını ortadan kaldıran uygulamam için hayati önemde olmayan bazı ivmeölçer örnekleme kodum vardı. Bu, simülatörün dikkate alındığı bir ivmeölçer olmadığını düşünüyor. Bu hataya neden olmadan bir hafta boyunca bu kodun el değmemiş, garip buluyorum ...
Héctor Ramos

Objective-C için yeniyim, bu yüzden problemlerimin çoğu bellek yönetiminden kaynaklanmalı. C ++ ile birkaç yıl sonra, son üç ya da dört yıldır çoğunlukla Java kullanıyorum, bu yüzden bellek yönetimi paslı oldum. Cevabınız için teşekkürler!
Héctor Ramos

4
Sorun değil - düzelttiğine sevindim. Bellek yönetiminin üstesinden gelmek gerçekten zor değil - sadece kuralları öğrendiğinizden ve iyi alışkanlıklara girdiğinizden emin olmanız gerekir.
philsquared

Yaşadığım sorun sadece yarattığım dizeleri (ve benzeri) serbest bırakmak için çok agresif olmak gibi görünüyor. Neyin ne zaman ve ne zaman yayınlanması gerektiğinden hala% 100 emin değilim, ancak Phil'in cevabı kesinlikle yardımcı oldu.
pluckyglen

Eğer doğru takip etsem, cmculloh, evet bu doğru olan şeydi. ObjectAtIndex öğesinden nesne dönüşüne sahip değilsiniz.
philsquared

101

EXC_BAD_ACCESS'in başlıca nedeni, serbest bırakılan nesnelere erişmeye çalışmaktır.

Bu sorunu nasıl gidereceğinizi öğrenmek için şu belgeyi okuyun: DebuggingAutoReleasePool

"Otomatik olarak serbest bırakılan nesneleri serbest bıraktığınızı" düşünmeseniz bile, bu durum sizin için geçerli olacaktır.

Bu yöntem son derece iyi çalışıyor. Her zaman büyük bir başarı ile kullanıyorum !!

Özetle, kodunuzda tam olarak hangi nesneye erişildiğini bulmak için Cocoa'nın NSZombie hata ayıklama sınıfının ve komut satırı "malloc_history" aracının nasıl kullanılacağı açıklanmaktadır.

Kenar notu:

Enstrümanları çalıştırmak ve sızıntıları kontrol etmek EXC_BAD_ACCESS sorunlarının giderilmesine yardımcı olmaz. Bellek sızıntılarının EXC_BAD_ACCESS ile ilgisi olmadığından eminim. Bir sızıntının tanımı, artık erişemeyeceğiniz bir nesnedir ve bu nedenle onu çağıramazsınız.

GÜNCELLEME: Artık Sızıntıları gidermek için Cihazlar kullanıyorum. Xcode 4.2'den Ürün-> Profil'i seçin ve Cihazlar açıldığında "Zombiler" i seçin.


18
Bu sidenote çok önemlidir. Sızıntılar EXC_BAD_ACCESS'e neden olamaz (başka sorunları da vardır). Bunu EXC_BAD_ACCESS hakkındaki yanlış düşünceleri
Lou Franco

4
Xcode'daki bu zombiler aracı mükemmel! Ben suçlu bulundu değil 3 dakika içinde saat.
Aram Kocharyan

1
cevaptaki yukarıdaki bağlantı mevcut değil. 404 bulunamadı hatasını gösterir.
Tejas

12

EXC_BAD_ACCESS sinyali, sistem çağrısına geçersiz bir işaretçi iletilmesinin sonucudur. OS X üzerinde bir test programı ile bugün daha erken bir tane aldım - pthread_join()daha önce yazım hatası nedeniyle başlatılmamış bir değişkeni geçiyordum .

İPhone geliştirmeye aşina değilim, ancak sistem çağrılarına ilettiğiniz tüm arabellek işaretleyicilerinizi iki kez kontrol etmelisiniz. Derleyicinizin uyarı düzeyini sonuna kadar artırın (gcc ile -Wallve -Wextraseçeneklerini kullanın ). Simülatör / hata ayıklayıcıda mümkün olduğunca çok tanılama etkinleştirin.


8

Deneyimlerime göre, bu genellikle yasadışı bir bellek erişiminden kaynaklanır. Başlatıldıklarından emin olmak için tüm işaretçileri, özellikle nesne işaretlerini kontrol edin. MainWindow.xib dosyanızın, eğer kullanıyorsanız, gerekli tüm bağlantılarla düzgün şekilde kurulduğundan emin olun.

Kağıt üzerinde yapılan kontrollerden hiçbiri bir şey açmazsa ve tek adımda gerçekleşmezse, hatayı NSLog () ifadeleriyle bulmaya çalışın: kodunuzu onlarla birlikte serpiştirin, neden olan satırı izole edene kadar hareket ettirin hata. Sonra bu satırda bir kesme noktası belirleyin ve programınızı çalıştırın. Kesme noktasına geldiğinizde, beklediğiniz gibi görünmeyen bir şey olup olmadığını görmek için tüm değişkenleri ve içindeki nesneleri inceleyin. Özellikle nesne sınıfı beklemediğiniz bir şey olan değişkenlere dikkat edin. Bir değişkenin bir UIWindow içermesi gerekiyorsa ancak bunun içinde bir NSNotification varsa, hata ayıklayıcı çalışmadığında aynı temel kod hatası farklı bir şekilde kendini gösterebilir.


7

Ben sadece bir EXC_BAD_ACCESS izlemek birkaç saat geçirdim ve NSZombies ve diğer env vars bana bir şey söylemek gibi görünmüyordu bulundu.

Benim için, biçim belirteçleri olan aptal bir NSLog deyimiydi, ancak argümanlar geçmedi.

NSLog(@"Some silly log message %@-%@");

Tarafından düzeltildi

NSLog(@"Some silly log message %@-%@", someObj1, someObj2);

6

2010 WWDC videoları, apple geliştirici programındaki tüm katılımcılar tarafından kullanılabilir. Harika bir video var: "Oturum 311 - Enstrümanlar ile Gelişmiş Bellek Analizi", enstrümanlarda zombileri kullanmanın ve diğer hafıza problemlerini ayıklamanın bazı örneklerini gösteriyor.

Giriş sayfasına bağlantı için BURAYA tıklayın .


6

Tam bir cevap değil, ama bunu aldığım belirli bir durum, otomatik olarak kullanmaya çalıştığım için 'öldü' bir nesneye erişmeye çalışırken:

netObjectDefinedInMyHeader = [[[MyNetObject alloc] init] autorelease];

Örneğin, aslında bunu 'bildirmek' için bir nesne olarak geçiyordum (onu dinleyici, gözlemci, istediğiniz deyim olarak kaydettirdim) ama bildirim gönderildikten sonra zaten ölmüştü ve EXC_BAD_ACCESS'i alacağım. Bunu değiştirmek [[MyNetObject alloc] init]ve daha sonra uygun şekilde bırakmak hatayı çözdü.

Bunun olmasının bir başka nedeni, örneğin bir nesneyi iletip saklamaya çalışmanızdır:

myObjectDefinedInHeader = aParameterObjectPassedIn;

Daha sonra myObjectDefinedInHeader'a erişmeye çalışırken başınız derde girebilir. Kullanımı:

myObjectDefinedInHeader = [aParameterObjectPassedIn retain];

ihtiyacınız olan şey olabilir. Tabii ki bunlar, karşılaştığım şeylerin sadece birkaç örneği ve başka nedenler de var, ancak bunlar zor olabilir, bu yüzden onlardan bahsediyorum. İyi şanslar!


5

Bunun olabileceği başka bir durum eklemek için:

Kod vardı:

NSMutableString *string;
[string   appendWithFormat:@"foo"];

Açıkçası ben dize için bellek ayırmayı unutmuştu:

NSMutableString *string = [[NSMutableString alloc] init];
[string   appendWithFormat:@"foo"];

sorunu çözer.


Dize nil için başlatılır ve nil üzerinde bir yöntem çağıran null nesne kalıbı kullanarak hiçbir şey yapmaz çünkü bu benim için herhangi bir hataya neden olmaz.
Liron Yahdav

5

EXC_BAD_ACCESS istisnalarını gerçekleşmeden yakalamanın başka bir yöntemi de XCode 4+ içindeki statik analizördür .

Statik analiz cihazını Ürün> Analiz Et (shift + cmd + B) ile çalıştırın. Analizör tarafından oluşturulan herhangi bir iletiyi tıklatmak, kaynağınızdaki rahatsız edici nesnenin tutma / bırakma sırasını gösteren bir diyagramın üzerine yerleşecektir.

resim açıklamasını buraya girin


5

Ben objc_exception_throw bir kesme noktası ayarlamak yararlı buluyorum. Bu şekilde EXC_BAD_ACCESS'i aldığınızda hata ayıklayıcı kırılmalıdır.

Talimatları burada bulabilirsiniz Hata Ayıklama Teknikleri


4

"Eğer ayırmadıysanız veya saklamıyorsanız, bırakmayın" basit kuralını kullanın.


1
Bu kuralı "... kopyala ..." ile genişletin ve iyi olmalısınız.
kadar

4

EXC_BAD_ACCESS Nasıl Hata Ayıklanır

Yukarıdaki bağlantıya göz atın ve söylediği gibi yapın .... NSZombies'i kullanmak için bazı hızlı talimatlar

Uygulamayı çalıştırın ve başarısız olduktan sonra ("EXC_BAD_ACCESS" yerine "Kesildi" göstermelidir ... Konsolu (Çalıştır> Konsol) kontrol edin ... Şimdi hangi nesneye erişmeye çalıştığını söyleyen bir mesaj olmalıdır.

-Ben


3

Hata ayıklama ve son dört saattir bu hatayı çözmek için kodu yeniden düzenleme. Yukarıdaki bir yazı sorunu görmemi sağladı:

Önceki özellik: startPoint = [[DataPoint ayrılmış] init]; startPoint = [DataPointList objectAtIndex: 0];
. . . x = startPoint.x - 10; // EXC_BAD_ACCESS

Sonraki özellik: startPoint = [[DataPoint tahsis] init]; startPoint = [[DataPointList objectAtIndex: 0] koru];

Güle güle EXC_BAD_ACCESS


Benzer bir hata yaptım. Çarpışmaya neden olan örneği tekrar unutmayı unuttum ve anlamaya çalıştım. Deneyimim benimkini bulmak için beni yaktı. Teşekkürler!
David.Chu.ca

3

İşiniz bittiğinde 'string'i serbest bıraktığınızı umuyoruz!


3

Bir init-Metodu içinde kendini iade etmeyi unuttum ...;)


Bu, derleme zamanı uyarısı / hatası olmalı ve çalışma zamanı sırasında EXC_BAD_ACCESS olmamalıdır.
stigi

3

Bu mükemmel bir iplik. İşte benim deneyim: bir mülkiyet bildirimi üzerinde tutma / atama anahtar kelime ile berbat. Dedim:

@property (nonatomic, assign) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, assign) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, assign) IBOutlet UISwitch *asiaSwitch;

nerede söylemeliydim

@property (nonatomic, retain) IBOutlet UISegmentedControl *choicesControl;
@property (nonatomic, retain) IBOutlet UISwitch *africaSwitch;
@property (nonatomic, retain) IBOutlet UISwitch *asiaSwitch;

1
Tuhaf, neden IBOutlet'i tutmanız gerekiyor? Onların yönetimi sizin için otomatik olarak yapılır.
jv42

3

Ben sadece büyük bir dizi içeren bir C yöntemi yürütmeye çalışırken iPhone EXC_BAD_ACCESS karşılaştım. Simülatör bana kodu çalıştırmak için yeterli bellek verebildi, ancak cihazı değil (dizi bir milyon karakterdi, bu yüzden biraz aşırı oldu!).

EXC_BAD_ACCESS, yöntemin giriş noktasından hemen sonra gerçekleşti ve dizi bildiriminin yakınında hiçbir yerde olmadığı için uzunca bir süre kafam karıştı.

Belki bir iki saat saçımı çekmekten yararlanabilir.


3

Olmayan bir alloc'd işaretçi almaya unuttum dealloc. Bir UINavigationController benim rootView exc_bad_access alıyordum, ama sadece bazen. Ben onun viewDidAppear {} yarı yolda çöküyordu çünkü sorunun rootView olduğunu varsayalım. Sadece ben kötü dealloc {} sürümü ile görüş patlattı sonra ortaya çıktı ve bu oldu!

"EXC_BAD_ACCESS" [330 işlemine geçiliyor] Şu anda programlanacak bellek yok: malloc'u aramak güvenli değil

Tahsis etmeye çalıştığım bir sorun olduğunu düşündüm ... tahsis edilmeyen bir yer bırakmaya çalıştığım yer değil, D'oh!


3

EXC_BAD_ACCESS ile nasıl başa çıkarım

Bazen bir EXC_BAD_ACCESS hatası atıldığında xcode, çökme gerçekleştiği yer hakkında ek bilgi veren main.m sınıfındaki hatayı göstereceğini hissediyorum.

O zamanlarda, Xcode'da İstisnai bir Kesme Noktası belirleyebiliriz, böylece istisna yakalandığında bir kesme noktası yerleştirilir ve kullanıcıya doğrudan bu satırda meydana gelen kilitlenme gerçekleştiğini bildirir

resim açıklamasını buraya girin


2

Yöntem parametrelerini doğrulamak için NSAssert () çağrıları, nils'i izlemek ve geçmek için de oldukça kullanışlıdır.


2

Sadece bu problemi yaşadım. Benim için sebep daha sonra başka bir yerden okumaya çalışarak bir CoreData yönetilen nesne ans silmek oldu.


2

Hata ayıklama ve son dört saattir bu hatayı çözmek için kodu yeniden düzenleme. Yukarıdaki bir yazı sorunu görmemi sağladı:

Önceki mülk:

startPoint = [[DataPoint alloc] init] ;
startPoint= [DataPointList objectAtIndex: 0];
x = startPoint.x - 10; // EXC_BAD_ACCESS

Şu tarihten sonraki mülkler:

startPoint = [[DataPoint alloc] init] ;
startPoint = [[DataPointList objectAtIndex: 0] retain];

Güle güle EXC_BAD_ACCESS

Cevabınız için çok teşekkür ederim. Bütün gün bu sorunla mücadele ediyorum. Harikasın!


4
Hemen startPoint'in üzerine yazmıyor musunuz? İlk satıra ihtiyacın olduğunu sanmıyorum.
toxaq

2
Hemen bir başkasıyla üzerine yazacaksanız, bir değişkeni tahsis etmeye ve başlatmaya kesinlikle gerek yoktur. Sadece ilk ödevdeki nesneyi sızdırıyorsunuz.
dreamlax

2

Sadece eklemek için

Lynda.com'da harika bir DVD var

iPhone SDK Temel Eğitimi

ve Bölüm 6, Ders 3 tamamen EXEC_BAD_ACCESS ve Zombies ile çalışmakla ilgilidir.

Anlamak benim için harikaydı, sadece hata kodunu değil, aynı zamanda yayınlanan nesne hakkında daha fazla bilgi almak için Zombies'i nasıl kullanabilirim.


2

Hatanın ne olabileceğini kontrol etmek için

NSZombieEnabled kullanın.

Uygulamanızda NSZombieEnabled özelliğini etkinleştirmek için:

Yürütülebilir Bilgi penceresini açmak için Proje> Etkin Yürütülebilirleri Düzenle'yi seçin. Bağımsız Değişkenler'i tıklayın. “Ortamda ayarlanacak değişkenler” bölümünde ekle (+) düğmesini tıklayın. Ad sütununa NSZombieEnabled ve Değer sütununa YES girin. NSZombieEnabled girişi için onay işaretinin seçili olduğundan emin olun.

Bu cevabı iPhoneSDK'da buldum


2

Bunun bir süre önce sorulduğunu fark ettim, ancak bu konuyu okuduktan sonra XCode 4.2 için çözüm buldum: Ürün -> Şemayı Düzenle -> Teşhis Sekmesi -> Zombi Nesnelerini Etkinleştir

Yeniden konumlandırılmış bir nesneye gönderilen bir iletiyi bulmama yardımcı oldu.


2

Sonsuz özyinelemeniz olduğunda, bu hatayı da alabileceğinizi düşünüyorum. Bu benim için bir davaydı.


1

Başka bir olasılık bile: blokları kuyruklarda kullanmak, başka bir kuyruktaki bir nesneye erişmeye çalışmanız, bu anda zaten ayrılmış durumda olabilir. Genellikle GUI'ye bir şey göndermeye çalıştığınızda. İstisna kesme noktanız garip bir yere ayarlanıyorsa, nedeni bu olabilir.


1

Anladım çünkü kullanmıyordum [self performSegueWithIdentifier:sender:]ve -(void) prepareForSegue:(UIstoryboardSegue *)doğru


1

@Dizeler oluştururken , neden olacağı C-stringsgibi davranarak sembolü unutmayın .NSStringsEXC_BAD_ACCESS

Bunu kullan:

@"Some String"

Bundan ziyade:

"Some String"

PS - genellikle bir arrayçok kayıt içeren bir içeriği doldururken .


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.