Konsola / oturum açma işlemine yığın izini nasıl yazdırırsınız?


293

Arama izini, başarısız iddialar veya yakalanmamış istisnalar gibi belirli noktalarda kaydetmek istiyorum.

Yanıtlar:


544
 NSLog(@"%@",[NSThread callStackSymbols]);

Bu kod herhangi bir iş parçacığında çalışır.


14
Bu soru ilk sorulduğunda mevcut olmayan Mac OS X 10.6'daki yenilikler. Kar-Leopar öncesi için backtraceve backtrace_symbolsişlevlerini kullanın ; arka iz (3) kılavuzuna bakınız.
Peter Hosey

6
Yalnızca iOS 4.0 ve sonraki sürümlerde.
Danra

Teşekkürler! Bunu sadece yığın izini yazdırmanın bir yolu var mı, mesela, tüm yol yerine 6 seviye aşağı?
sudo

9000, backtrace/backtrace_symbolsdoğrudan kullanın
dymv

34

n13'ün cevabı pek işe yaramadı - bunu bulmak için biraz değiştirdim

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char *argv[])
{
    @autoreleasepool {
        int retval;
        @try{
            retval = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
        @catch (NSException *exception)
        {
            NSLog(@"Gosh!!! %@", [exception callStackSymbols]);
            @throw;
        }
        return retval;
    }
}

4
Gah ... Apple bir uygulama geliştirirken bunu en azından bir standart haline getirmeli. Bir grup bellek adresi ... arkaik
Russ

İyileşmelerinizi cevabıma koydum; Bunu ARC'den önce yaptım. Teşekkürler.
n13

1
Bu vermez her durumda çalışmayabilir. Tüm yakalanmamış istisnaları yakalamak istiyorsanız bu daha iyi bir yaklaşımdır: codereview.stackexchange.com/questions/56162/… (Bu sorudaki kod biraz fazla karmaşıktır, ancak aynı zamanda çağrı yığını sembollerini günlüğe kaydetmekten daha fazlasını yapar.)
nhgrif

İsterseniz NSLog(@"[Error] - %@ %@", exception.name, exception.reason);gerçek istisna da ekleyebilirsiniz
Corentin S.

9

Cocoa, ham bellek adresleri olmasına rağmen, konsoldaki yakalanmamış istisnalar üzerinde yığın izini zaten kaydeder. Konsolda sembolik bilgi istiyorsanız bazı örnek kodlar vardır Apple'ın .

Kodunuzda rastgele bir noktada yığın izlemesi oluşturmak istiyorsanız (ve Leopard'daysanız), geri izleme man sayfasına bakın. Leopard'dan önce, aslında çağrı yığınının kendisini kazmanız gerekiyordu.


6
Görünüşe göre iOS 4'te mevcut, ancak 3.2'de mevcut değil. Kullandığım şey, geri izleme man sayfasından utanmadan kopyalandı: #include <execinfo.h> ... void * callstack [128]; int i, kareler = geri iz (calltack, 128); char ** strs = backtrace_symbols (çağrı damgası, çerçeveler); (i = 0; i <kare; ++ i) {printf ("% s \ n", strs [i]); } serbest (strs);
mharper

HandleException çağrıldığında işleyici işlevinin izini geri yazarken, [NSException callStackSymbols] kural dışı durumun arttığı yerin yığınını gösterir. Ancak "backtrace (...)" yerine "NSArray arr = [ex callStackReturnAddresses]; int frames = arr.count; (i = 0; i <kare; ++ i) çağrıları [i] = ( void) [((NSNumber *) [arr objectAtIndex: i]) intValue]; " geçerli istisna yığını izleme alacaksınız. Sanırım [NSException callStackSymbols] bu şekilde çalışır, sanırım: geri döndükleri izler eşittir ve her iki uygulama çağrısında da sürümde _mh_execute_header kullanılır.
Tertium

6

Bu size hemen hemen ne yapacağınızı söyler.

Temelde, günlüğe kaydetmek için uygulamalar istisna işleme ayarlamanız gerekir, örneğin:

#import <ExceptionHandling/NSExceptionHandler.h>

[[NSExceptionHandler defaultExceptionHandler] 
                  setExceptionHandlingMask: NSLogUncaughtExceptionMask | 
                                            NSLogUncaughtSystemExceptionMask | 
                                            NSLogUncaughtRuntimeErrorMask]

1
Bununla birlikte, bunun yalnızca kayıtlı bir istisna işleyicisi içinde çalışacağını unutmayın (örneğin, bir @catch bloğunda değil)
Barry Wark


1

Bu şekilde hızlı bir şekilde yazdırın:

print("stack trace:\(Thread.callStackSymbols)")
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.