ios程序发布后,收集Crash崩溃信息

iOS平台一套完善的Crash Report解决方案 最开始想iOS和Android都做了,后面尝试了下android上面的崩溃收集,困难程度超出我的想象,也可以说几乎不可能实现像iOS下面一样实用且方便的崩溃收集系统(1.有堆栈等信息,不会产生卡死等副作用。  2.专指jni崩溃,java的崩溃很容易处理)。  这个有一点要反思一下,在困难的地方浪费时间不如把简单的东西做好,那么多赚大钱的游戏也是各种不完美,但是玩家不会在意程序是否牛x,技术是否高 阅读详情

有人想在iOS程序发布之后,收集程序崩溃的信息以便改进程序,今天我给大家介绍个比较实用的方法。

崩溃信息的收集完成后会在沙盒生成txt报告,但是这个crash收集也不能收集所有的程序崩溃信息,例如栈溢出或者对象指针损坏等等,这些崩溃会导致Crash收集的代码不会执行。

废话不多说,先直接讲添加方法,源代码一起奉献;

在appdelegate里的 application:didFinishLoading方法中添加

[[CrashManager sharedInstance] manageCrashes];

当然,你也能设置代理让你的delegate接受崩溃信息,

[[CrashManager sharedInstance] setCrashDelegate:self selector:@selector(notifyException:stackTrace:)];

下面是源代码:CrashManager.h

#import <Foundation/Foundation.h>
#import "SynthesizeSingleton.h"


/**
 * Manages any crashes that occur while the app is running.
 * If a crash occurs while CrashManager is managing crashes, it will write
 * a crash report to a file, allow a user-defined delegate to do some more processing,
 * then let the application finish crashing.
 */
@interface CrashManager : NSObject
{
    /** The full path to the error report that this manager will write to. */
    NSString* errorReportPath;

    /** The delegate to inform when a crash occurs (can be nil). */
    id delegate;

    /** The selector to call on the delegate. */
    SEL callbackSelector;
}

SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(CrashManager);

/**
 * Start managing crashes.
 */
- (void) manageCrashes;

/**
 * Stop managing crashes.
 */
- (void) stopManagingCrashes;

/** The error report's path.
 * Note: If you set this to a value that doesn't start with "/", it will
 *       be expanded to a full path relative to the Documents directory.
 */
@property(readwrite,nonatomic,retain) NSString* errorReportPath;

/** The error report.  If there is no report, this will be nil. */
@property(readonly,nonatomic) NSString* errorReport;

/** If true, there is an error report present. */
@property(readonly,nonatomic) bool errorReportPresent;

/**
 * Delete the error report (if any).
 */
- (void) deleteErrorReport;

/**
 * Set the delegate and selector to call when a crash occurs.
 * The selector must take an NSException* and NSArray* parameter like so: <br>
 * - (void) notifyException:(NSException*) exception stackTrace:(NSArray*) stackTrace <br>
 * stackTrace will be an array of StackTraceEntry.
 *
 * @param delegate The delegate to call.
 * @param selector The selector to invoke.
 */
- (void) setCrashDelegate:(id) delegate selector:(SEL) selector;


@end


然后是CrashManager.m

#import "CrashManager.h"
#include <unistd.h>
#import "StackTracer.h"
#import <UIKit/UIKit.h>
#import "MacAdress.h"
#import "NSString+SHA.h"

/** Maximum number of stack frames to capture. */
#define kStackFramesToCapture 40

/** The default file to store error reports to. */
#define kDefaultReportFilename @"error_report.txt"

/** The exception name to use for raised signals. */
#define kSignalRaisedExceptionName @"SignalRaisedException"


@interface CrashManager (Private)

/**
 * Called automatically to handle an exception.
 *
 * @param exception The exception that was raised.
 * @param stackTrace The stack trace.
 */
- (void) handleException:(NSException*) exception stackTrace:(NSArray*) stackTrace;

/**
 * Called automatically to handle a raised signal.
 *
 * @param signal The signal that was raised.
 * @param stackTrace The stack trace.
 */
- (void) handleSignal:(int) signal stackTrace:(NSArray*) stackTrace;

/**
 * Get the name of a signal.
 *
 * @param signal The signal to get a name for.
 * @return The name of the signal.
 */
- (NSString*) signalName:(int) signal;

/**
 * Store an exception and stack trace to disk.
 * It will be stored to the file specified in reportFilename.
 *
 * @param exception The exception to store.
 * @param stackTrace The stack trace to store.
 */
- (void) storeErrorReport:(NSException*) exception stackTrace:(NSArray*) stackTrace;

@end


/**
 * Install the exception and signal handlers.
 */
static void installHandlers();

/**
 * Remove the exception and signal handlers.
 */
static void removeHandlers();

/**
 * Exception handler.
 * Sets up an appropriate environment and then calls CrashManager to
 * deal with the exception.
 *
 * @param exception The exception that was raised.
 */
static void handleException(NSException* exception);

/**
 * Signal handler.
 * Sets up an appropriate environment and then calls CrashManager to
 * deal with the signal.
 *
 * @param exception The exception that was raised.
 */
static void handleSignal(int signal);



static void installHandlers()
{
    NSSetUncaughtExceptionHandler(&handleException);
    signal(SIGILL, handleSignal);
    signal(SIGABRT, handleSignal);
    signal(SIGFPE, handleSignal);
    signal(SIGBUS, handleSignal);
    signal(SIGSEGV, handleSignal);
    signal(SIGSYS, handleSignal);
    signal(SIGPIPE, handleSignal);
}

static void removeHandlers()
{
    NSSetUncaughtExceptionHandler(NULL);
    signal(SIGILL, SIG_DFL);
    signal(SIGABRT, SIG_DFL);
    signal(SIGFPE, SIG_DFL);
    signal(SIGBUS, SIG_DFL);
    signal(SIGSEGV, SIG_DFL);
    signal(SIGSYS, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
}

static void handleException(NSException* exception)
{
    removeHandlers();
    
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    
    NSArray* stackTrace = [[StackTracer sharedInstance] generateTraceWithMaxEntries:kStackFramesToCapture];
    [[CrashManager sharedInstance] handleException:exception stackTrace:stackTrace];
    
    [pool drain];
    [exception raise];
}

static void handleSignal(int signal)
{
    removeHandlers();
    
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    
    NSArray* stackTrace = [[StackTracer sharedInstance] generateTraceWithMaxEntries:kStackFramesToCapture];
    [[CrashManager sharedInstance] handleSignal:signal stackTrace:stackTrace];
    
    [pool drain];
    // Note: A signal doesn't need to be re-raised like an exception does.
}


@implementation CrashManager


SYNTHESIZE_SINGLETON_FOR_CLASS(CrashManager);

- (id) init
{
    if(nil != (self = [super init]))
    {
        self.errorReportPath = kDefaultReportFilename;
    }
    return self;
}

- (void) dealloc
{
    [errorReportPath release];
    [super dealloc];
}

- (void) setCrashDelegate:(id) delegateIn selector:(SEL) selectorIn
{
    delegate = delegateIn;
    callbackSelector = selectorIn;
}

- (void) manageCrashes
{
    installHandlers();
}

- (void) stopManagingCrashes
{
    removeHandlers();
}

- (NSString*) errorReportPath
{
    return errorReportPath;
}

- (void) setErrorReportPath:(NSString*) filename
{
    if([filename characterAtIndex:0] != '/')
    {
        NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString* dir = [paths objectAtIndex:0];
        errorReportPath = [[dir stringByAppendingPathComponent:filename] retain];
    }
    else
    {
        errorReportPath = [filename retain];
    }
    
}

- (bool) errorReportPresent
{
    return [[NSFileManager defaultManager] fileExistsAtPath:errorReportPath];
}

- (NSString*) errorReport
{
    NSError *error = nil;
    return [NSString stringWithContentsOfFile:errorReportPath encoding:NSUTF8StringEncoding error:&error];
}

- (void) deleteErrorReport
{
    NSError *error = nil;
    [[NSFileManager defaultManager] removeItemAtPath:errorReportPath error:&error];
    if(nil != error)
    {
        NSLog(@"Warning: %s: Could not delete %@: %@", __PRETTY_FUNCTION__, errorReportPath, error);
    }
}

- (void) handleException:(NSException*) exception stackTrace:(NSArray*) stackTrace
{
    [self storeErrorReport:exception stackTrace:stackTrace];
    [delegate performSelector:callbackSelector withObject:exception withObject:stackTrace];
}

- (void) handleSignal:(int) signal stackTrace:(NSArray*) stackTrace
{
    NSException* exception = [NSException exceptionWithName:kSignalRaisedExceptionName
                                                     reason:[self signalName:signal]
                                                   userInfo:nil];
    [self storeErrorReport:exception stackTrace:stackTrace];
    [delegate performSelector:callbackSelector withObject:exception withObject:stackTrace];
}

- (void) storeErrorReport:(NSException*) exception stackTrace:(NSArray*) stackTrace
{
    NSString* data = [NSString stringWithFormat:@"=============异常崩溃报告=============\n%@\nApp: %@\nVersion: %@\nID: %@\nReason: %@: %@\n%@\n\n\n",
                      [NSDate date],
                      [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"],
                      [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"],
                      [[MacAdress macAdress] sha1],
            [exception name],
                      [exception reason],
                      [[StackTracer sharedInstance] printableTrace:stackTrace]];
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:errorReportPath]) {
        NSString *tmp = [NSString stringWithContentsOfFile:errorReportPath encoding:NSUTF8StringEncoding error:nil];
        data = [tmp stringByAppendingFormat:@"%@",data];
    }
    [data writeToFile:errorReportPath atomically:YES encoding:NSUTF8StringEncoding error:nil];
}

- (NSString*) signalName:(int) signal
{
    switch(signal)
    {
        case SIGABRT:
            return @"Abort";
        case SIGILL:
            return @"Illegal Instruction";
        case SIGSEGV:
            return @"Segmentation Fault";
        case SIGFPE:
            return @"Floating Point Error";
        case SIGBUS:
            return @"Bus Error";
        case SIGPIPE:
            return @"Broken Pipe";
        default:
            return [NSString stringWithFormat:@"Unknown Signal (%d)", signal];
    }
}

@end



具体错误路径的StackTracer.h

#import <Foundation/Foundation.h>
#import "SynthesizeSingleton.h"


/**
 * Generates and formats stack traces.
 */
@interface StackTracer : NSObject
{
    /** The current application process's name. */
    NSString* processName;
}

/** Make this class into a singleton. */
SYNTHESIZE_SINGLETON_FOR_CLASS_HEADER(StackTracer);

/**
 * Generate a stack trace with the default maximum entries (currently 40).
 *
 * @return an array of StackTraceEntry.
 */
- (NSArray*) generateTrace;

/**
 * Generate a stack trace with the specified maximum entries.
 *
 * @param maxEntries The maximum number of lines to trace.
 * @return an array of StackTraceEntry.
 */
- (NSArray*) generateTraceWithMaxEntries:(unsigned int) maxEntries;

/**
 * Create an "intelligent" trace from the specified trace.
 * This is designed primarily for stripping out useless trace lines from
 * an exception or signal trace.
 *
 * @param stackTrace The trace to convert (NSArray containing StackTraceEntry).
 * @return An intelligent trace with the useless info stripped.
 */
- (NSArray*) intelligentTrace:(NSArray*) stackTrace;

/**
 * Turn the specified stack trace into a printabe string.
 *
 * @param stackTrace The stack trace to convert (NSArray containing StackTraceEntry).
 * @retun A string representation of the stack trace.
 */
- (NSString*) printableTrace:(NSArray*) stackTrace;

/**
 * Turn the specified stack trace into a condensed printable string.
 * The condensed entries are space separated, and only contain the object class
 * (if any) and the selector call.
 *
 * @param stackTrace The stack trace to convert (NSArray containing StackTraceEntry).
 * @return A condensed string representation of the stack trace.
 */
- (NSString*) condensedPrintableTrace:(NSArray*) stackTrace;

@end





/**
 * A single stack trace entry, recording all information about a stack trace line.
 */
@interface StackTraceEntry: NSObject
{
    unsigned int traceEntryNumber;
    NSString* library;
    unsigned int address;
    NSString* objectClass;
    bool isClassLevelSelector;
    NSString* selectorName;
    int offset;
    NSString* rawEntry;
}
/** This entry's position in the original stack trace. */
@property(readonly,nonatomic) unsigned int traceEntryNumber;

/** Which library, framework, or process the entry is from. */
@property(readonly,nonatomic) NSString* library;

/** The address in memory. */
@property(readonly,nonatomic) unsigned int address;

/** The class of object that made the call. */
@property(readonly,nonatomic) NSString* objectClass;

/** If true, this is a class level selector being called. */
@property(readonly,nonatomic) bool isClassLevelSelector;

/** The selector (or function if it's C) being called. */
@property(readonly,nonatomic) NSString* selectorName;

/** The offset within the function or method. */
@property(readonly,nonatomic) int offset;

/** Create a new stack trace entry from the specified trace line.
 * This line is expected to conform to what backtrace_symbols() returns.
 */
+ (id) entryWithTraceLine:(NSString*) traceLine;

/** Initialize a stack trace entry from the specified trace line.
 * This line is expected to conform to what backtrace_symbols() returns.
 */
- (id) initWithTraceLine:(NSString*) traceLine;

@end




StackTracer.m

#import "StackTracer.h"
#include <execinfo.h>
#include <unistd.h>


/** The maximum number of stack trace lines to use if none is specified. */
#define kDefaultMaxEntries 40

@implementation StackTracer

SYNTHESIZE_SINGLETON_FOR_CLASS(StackTracer);

- (id) init
{
    if(nil != (self = [super init]))
    {
        processName = [[[NSProcessInfo processInfo] processName] retain];
    }
    return self;
}

- (void) dealloc
{
    [processName release];
    [super dealloc];
}

- (NSArray*) generateTrace
{
    return [self generateTraceWithMaxEntries:kDefaultMaxEntries];
}

- (NSArray*) generateTraceWithMaxEntries:(unsigned int) maxEntries
{
    // Get the stack trace from the OS.
    void* callstack[maxEntries];
    int numFrames = backtrace(callstack, maxEntries);
    char** symbols = backtrace_symbols(callstack, numFrames);
    
    // Create StackTraceEntries.
    NSMutableArray* stackTrace = [NSMutableArray arrayWithCapacity:numFrames];
    for(int i = 0; i < numFrames; i++)
    {
        [stackTrace addObject:[StackTraceEntry entryWithTraceLine:[NSString stringWithUTF8String:symbols[i]]]];
    }
    
    // symbols was malloc'd by backtrace_symbols() and so we must free it.
    free(symbols);
    
    return stackTrace;
}

- (NSArray*) intelligentTrace:(NSArray*) stackTrace
{    
    int startOffset = 0;

    // Anything with this process name at the start is going to be part of the
    // exception/signal catching.  We skip that.
    for(int i = startOffset; i < [stackTrace count]; i++)
    {
        StackTraceEntry* entry = [stackTrace objectAtIndex:i];
        if(![processName isEqualToString:entry.library])
        {
            startOffset = i;
            break;
        }
    }
    
    // Beneath that is a bunch of runtime error handling stuff.  We skip this as well.
    for(int i = startOffset; i < [stackTrace count]; i++)
    {
        StackTraceEntry* entry = [stackTrace objectAtIndex:i];
        
        if(0xffffffff == entry.address)
        {
            // Signal handler stack trace is useless up to "0xffffffff 0x0 + 4294967295"
            startOffset = i + 1;
            break;
        }
        if([@"__objc_personality_v0" isEqualToString:entry.selectorName])
        {
            // Exception handler stack trace is useless up to "__objc_personality_v0 + 0"
            startOffset = i + 1;
            break;
        }
    }

    // Look for the last point where it was still in our code.
    // If we don't find anything, we'll just use everything past the exception/signal stuff.
    for(int i = startOffset; i < [stackTrace count]; i++)
    {
        StackTraceEntry* entry = [stackTrace objectAtIndex:i];
        // If we reach the "main" function, we've exhausted the stack trace.
        // Since we couldn't find anything, start from the previously calculated starting point.
        if([@"main" isEqualToString:entry.selectorName])
        {
            break;
        }
        
        // If we find something from our own code, use one level higher as the starting point.
        if([processName isEqualToString:entry.library])
        {
            startOffset = i - 1;
            break;
        }
    }
    
    NSMutableArray* result = [NSMutableArray arrayWithCapacity:[stackTrace count] - startOffset];
    for(int i = startOffset; i < [stackTrace count]; i++)
    {
        StackTraceEntry* entry = [stackTrace objectAtIndex:i];
        // We don't care about intermediate forwarding functions.
        if(![@"___forwarding___" isEqualToString:entry.selectorName] &&
           ![@"_CF_forwarding_prep_0" isEqualToString:entry.selectorName])
        {
            [result addObject:[stackTrace objectAtIndex:i]];
        }
    }
    
    return result;
}


- (NSString*) printableTrace:(NSArray*) stackTrace
{
    NSMutableString* string = [NSMutableString stringWithCapacity:[stackTrace count] * 100];
    for(StackTraceEntry* entry in stackTrace)
    {
        [string appendString:[entry description]];
        [string appendString:@"\n"];
    }
    return string;
}

- (NSString*) condensedPrintableTrace:(NSArray*) stackTrace
{
    NSMutableString* string = [NSMutableString stringWithCapacity:[stackTrace count] * 50];
    bool firstRound = YES;
    for(StackTraceEntry* entry in stackTrace)
    {
        if(firstRound)
        {
            firstRound = NO;
        }
        else
        {
            // Space separated.
            [string appendString:@" "];
        }

        if(nil != entry.objectClass)
        {
            // -[MyClass myMethod:anExtraParameter] or
            // +[MyClass myClassMethod:anExtraParameter]
            NSString* levelPrefix = entry.isClassLevelSelector ? @"+" : @"-";
            [string appendFormat:@"%@[%@ %@]", levelPrefix, entry.objectClass, entry.selectorName];
        }
        else
        {
            // my_c_function
            [string appendFormat:@"%@", entry.selectorName];
        }
    }
    return string;
}

@end



@implementation StackTraceEntry

static NSMutableCharacterSet* objcSymbolSet;

+ (id) entryWithTraceLine:(NSString*) traceLine
{
    return [[[self alloc] initWithTraceLine:traceLine] autorelease];
}

- (id) initWithTraceLine:(NSString*) traceLine
{
    if(nil == objcSymbolSet)
    {
        objcSymbolSet = [[NSMutableCharacterSet alloc] init];
        [objcSymbolSet formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
        [objcSymbolSet formUnionWithCharacterSet:[NSCharacterSet characterSetWithRange:NSMakeRange('!', '~' - '!')]];
    }
    
    if(nil != (self = [super init]))
    {
        rawEntry = [traceLine retain];
        
        NSScanner* scanner = [NSScanner scannerWithString:rawEntry];
        
        if(![scanner scanInt:(int*)&traceEntryNumber]) goto done;
        
        if(![scanner scanUpToString:@" 0x" intoString:&library]) goto done;
        
        if(![scanner scanHexInt:&address]) goto done;
        
        if(![scanner scanCharactersFromSet:objcSymbolSet intoString:&selectorName]) goto done;
        if([selectorName length] > 2 && [selectorName characterAtIndex:1] == '[')
        {
            isClassLevelSelector = [selectorName characterAtIndex:0] == '+';
            objectClass = [[selectorName substringFromIndex:2] retain];
            if(![scanner scanUpToString:@"]" intoString:&selectorName]) goto done;
            if(![scanner scanString:@"]" intoString:nil]) goto done;
        }
        
        if(![scanner scanString:@"+" intoString:nil]) goto done;
        
        if(![scanner scanInt:&offset]) goto done;
        
    done:
        if(nil == library)
        {
            library = @"???";
        }
        if(nil == selectorName)
        {
            selectorName = @"???";
        }
        [library retain];
        [objectClass retain];
        [selectorName retain];
    }
    return self;
}

- (void) dealloc
{
    [rawEntry release];
    [library release];
    [objectClass release];
    [selectorName release];
    [super dealloc];
}

@synthesize traceEntryNumber;
@synthesize library;
@synthesize address;
@synthesize objectClass;
@synthesize isClassLevelSelector;
@synthesize selectorName;
@synthesize offset;

- (NSString*) description
{
    return rawEntry;
}

@end


有想要完整demo工程的,请移步下载。稍后给出链接。


iOS 26 崩溃日志深度指南,如何收集、符号化、定位与监控 本文聚焦 iOS 26 崩溃日志处理,讲解新版系统中可能的 SDK 与 API 崩溃风险,介绍如何用 Xcode + dSYM + KeyMob 捕获、符号化、分析崩溃日志,结合典型案例(如 EXC_BREAKPOINT / URLSession 崩溃)提供实战流程与定位策略。 阅读详情

相关推荐

iOS奔溃分析技巧-crash日志符号化

前言 iOS开发需要不停发版本,开发者要面临线上各种版本的奔溃日志(crash log),解决奔溃问题是移动开发者最日常的工作之一. 在实际的项目开发中,崩溃问题,依赖xcode,依赖于系统记录的崩溃日志或错误堆栈,在本地开发调试阶段,是没有问题的。 如果在发布的线上版本出现崩溃问题,开发者是无法即时准确的取得错误堆栈的,需要获取到crash日志,进行相应处理。 简单的崩溃还好说,复杂的崩...

代码手工艺术家的专栏 2344

C++ 23 的栈踪迹库(stacktrace)

许多编程语言都提供调用栈踪迹回溯的功能,在错误发生的时候,除了报告错误发生的位置,还能输出函数调用栈信息。现在,C++ 也有自己的栈踪迹库了

oRbIt 的专栏 2287

Crash-Manager, 用于记录崩溃事件的iOS库.zip

Crash-Manager, 用于记录崩溃事件的iOS库 重要说明:这个崩溃管理器不处理所有可能的崩溃情况。 有一些( 。如堆栈溢出或者已损坏的对象指针) 崩溃可能导致崩溃管理器失败,并不会记录崩溃。一个更健壮的解决方案在这里是有用的。崩溃管理器用于记录崩溃事件的iOS库。许可证卡尔

iOS异常捕获

前言 在阅读文章之前,建议大家在阅读完此篇文章后可以阅读漫谈iOS Crash收集框架,了解一下原理。 开发iOS应用,解决Crash问题始终是一个难题。Crash分为两种,一种是由EXC_BAD_ACCESS引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;另一种是未被捕获的Objective-C异常(NSException),导致程序向自身发送了SIGABRT信号

sadlike的专栏 1223

F280049C_HRPWM_死区时间高精度控制与MEP技术实战解析

本文深入解析了F280049C的HRPWM模块及其基于MEP技术的死区时间高精度控制。通过实测数据与TI官方代码对比,详细阐述了DBREDHR和DBFEDHR寄存器的配置技巧、精度优化方法及常见问题调试,为电源管理和电机控制应用提供了实用的实战指南。

yolo5detector的博客 217

动态规划与状态压缩:从TSP问题理解算法优化核心思想

动态规划是一种通过将复杂问题分解为重叠子问题并存储中间结果来避免重复计算的核心算法思想,广泛应用于路径优化、资源分配和序列决策等场景。其核心原理在于最优子结构和无后效性,通过状态设计和状态转移方程,将指数级复杂度问题转化为多项式时间可解。在工程实践中,状态压缩技术常被用于高效表示集合状态,例如使用二进制位运算来操作城市访问集合,从而大幅提升算法效率。本文以经典的旅行商问题(TSP)为例,深入剖析如何运用动态规划与状态压缩技术,将暴力穷举的指数级复杂度优化为可管理的计算量,为解决组合优化问题提供了重要的方法论

weixin_32075843的博客 365

ios崩溃日志收集_iOS崩溃日志收集与解析

收集crash日志方式1.设备上直接查看路径:设置 -> 隐私 -> 分析 -> 分析数据2.xcode获取设备上信息路径:xcode菜单栏Window -> Devices and Simulators -> 选中设备 -> View Device Logs3.xcode获取发布版本崩溃信息路径:xcode菜单栏Window -> Organizer -...

weixin_39754616的博客 812

U盘重装Win10系统

准备工作 准备一个8G或8G以上U盘(32G以内) 请备份好u盘里的资料,在制作过程中会格式化硬盘 请备份好要安装系统的盘的资料,安装时也会对该盘内容进行格式化。 将u盘插入电脑usb接口中,尽可能的插入usb3.0的接口,这样下载和安装速度会更快。 1.到微软官网下载安装包 浏览器输入:微软官网下载win10 懒人请复制粘贴:https://www.microsoft.com/zh-cn/software-download/windows10 ​ 打开之后的界面: 2.下载Media Creat.

Cici$的博客 2116

iOS Crash收集与分析详解(基础篇)

前言: 最近测试妹子老是抱怨我偶现的Bug不好复现,我这边出于偷懒(其实是工作很忙)一直再说不能复现Bug的妹子不是好测试,最近闲下来了,正好谈谈Crash的收集和分析。 一、Crash收集 噔噔噔噔~万能的官方文档又出现了,先上地址Understanding and Analyzing Application Crash Reports Crash收集与解析流程图 通过上图我们可以发现Crash的收集主要有两种方式。 1、使用Xcode从设备获取崩溃日志: 如果你把你的手机连接到Mac

feelinghappy的专栏 2729

基于springboot生鲜食品订购系统的设计与实现

近年来互联网络的迅猛发展和电子终端设备的普及,赋予了各行业充足的发展空间。微信小程序的O2O生鲜食品订购相比于传统信息技术,时效性是它最大的特色,已经在电子娱乐、经济等中发挥着举足轻重的作用。短时间内迅速扩大了线上管理系统的规模。尽管O2O生鲜食品订购已经有了很大程度的发展,但在微信小程序的O2O生鲜食品订购领域上却少有建设。

1024

【即插即用模块】注意力篇 | TGRS 2025 | ASD:自适应频域解耦,动态拆分高低频+空间注意力,频域空间特征双增强!

摘要: FDMF-Net提出了一种频域解耦多模态融合网络,核心组件为振幅谱解耦模块(ASD)。ASD通过自适应频域拆分和频域-空域协同增强,有效分离模态不变与模态特定特征。该模块利用MLP学习动态阈值调整高低频比例,并通过空间注意力分别强化频域特征,在遥感语义分割任务中实现了细节与结构的协同增强。实验表明,ASD模块能减少模态内冗余,提升特征判别性,为多模态数据融合提供了新思路。代码已开源,适用于需要强化细节与结构的视觉任务。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 309

IOS里用宏定义通用单例

程序里经常使用单例,可以做成一个简单的宏作为实现部分,来提高开发效率. MyClass类头文件里定义一个静态函数: + (MyClass*)sharedMyclass; 实现部分:SYNTHESIZE_SINGLETON_FOR_CLASS(MyClass); 定义宏如下: #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \  \

zhuangyou123的专栏 4060

STM32入门教程:水位传感器应用

这是一个简单的STM32水位检测系统的入门教程。希望通过学习本教程,您能对STM32微控制器的基本应用有更深入的了解,并能成功构建一个水位检测系统。如果您需要更详细的代码实例和教程,请参考相关的STM32开发手册和应用笔记。STM32是一款功能丰富且广泛应用于嵌入式系统的微控制器系列。在本教程中,我们将介绍如何使用STM32微控制器和水位传感器构建一个水位检测系统。

wx_linying1029的博客 533

【iOS】崩溃收集和解析

背景 在日常开发中,app难免会发生崩溃。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。 获取崩溃信息方式 在iOS中获取崩溃信息的方式有很多,比较常见的是使用友盟、云测、百度等第三方分析工具,或者自己收集崩溃信息并上传公司服务器。 下面列举一些我们常用的崩溃分析方式: 使用友盟、云测、百度等第三方崩溃统计工具。 自己实现应用内崩溃收集,并上传服务器。 Xcode-Devices中直接查看某个设备的崩溃信息。 使用苹果提供的Crash崩

BestpayTech的博客 2089

基于ResNet + LLM大语言模型的分类识别系统设计与实现,Web前后端分离,Django+vue3+AI助手模块+ResNet50算法+LLM 联动+Element Plus等技术,全网独发

分类识别任务是计算机视觉中的重要任务,广泛应用于智慧校园分类、智慧农业、智慧生活场景分类等领域。常见的分类模型有 VGGNet、ResNet 、MobileNet 、ConvNeXt、DenseNet、ViT、Swin Transformer、YOLOv8/11/26。本项目结合 ResNet分类识别算法 + LLM大语言模型联动 ,使用 Django + Vue3,构建了一个通用的 Web 前后端系统,用户端 + 管理端 ,便于用户操作检,不仅可以用于大论文的工作量展示,还可以作为毕业设计。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 760

OpenHarmony + AI:深度解析 Whisper.cpp 智慧语音系统级移植与 NAPI 封装实战

【代码】OpenHarmony + AI:深度解析 Whisper.cpp 智慧语音系统级移植与 NAPI 封装实战。

m0_67505153的博客 188

一文读懂iOS中的Crash捕获、分析以及防治

对于iOS端开发,定位和解决Crash毕竟两个流程,首先是根据线索来分析和定位问题,得到一个大概的猜想,之后按照自己的猜想去提供外部条件,来尝试复现问题,如果问题能够成功复现并复原与线程问题相似的堆栈现场,则基本完成了90%的工作,剩下的10%才是修复此问题。对于crash比例极低的,例如没有版本相关性的,对我们的应用影响极小的,我们可以通过去做AB实验尝试去修复。2.bad_access的排查途径有哪些?3.什么情况下会产生bad_access?

黑码哥的技术博客 2万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

iOS crash崩溃日志总结

引言 当游戏运行崩溃(也叫闪退)时,iOS系统生成对应的*.crash崩溃日志并保存在设备上。这份崩溃日志通常包含游戏闪退时当时运行的每个线程的堆栈调用信息,我们通过分析这些信息,定位游戏闪退发生的代码位置和异常类型。默认情况下,崩溃日志的堆栈调用信息是一堆16进制的内存地址和偏移量数字组成,如图 并不具有可读性。需要将其导入到Xcode,通过对应的dSYM文件和游戏包体,才能将这些数字转化成游戏代码里的调用方法名和所在文件的行数,如图, 从而生成我们可以分析的具体堆栈调用信息。 一、如何获取崩溃日志。

justbeme的专栏 1576

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

iOS Crash收集与分析

一、收集crash 1、使用Xcode从设备获取崩溃日志: 如果你把你的手机连接到Mac,并选择Xcode->Windows->Device and Simulator,然后点击View Device Logs,你会看到手机上会有好多Log,其中Type为Crash的就是崩溃的Log,如下图: 2、通过设备直接获取崩溃日志 1)打开设置->隐私->分析->分析数据,...

weixin_37543822的博客 343

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

如何符号化iOS系统的Crash日志

介绍如何获取Crash日志并符号化日志

专注于苹果IOS开发和最新资讯 3038

教你如何对ios崩溃(crash)日志做符号化

一、场景         客户端的开发流程都相似,如android,搞ios开发就要不停地发版本,随之而来的就是各种版本的崩溃日志(称为crash log)。如果不能好好地管理,那么开发人员很快就会在crash log和版本的海洋里迷失方向。解决崩溃问题是移动应用开发者最日常的工作之一。如果是开发过程中遇到的崩溃,可以根据重现步骤调试,但线上版本就无能为力了。         国内,一

Weiguang_123的专栏 2万+

iOS崩溃crash大解析

前言 iOS崩溃是让iOS开发人员比较头痛的事情,app崩溃了,说明代码写的有问题,这时如何快速定位到崩溃的地方很重要。调试阶段是比较容易找到出问题的地方的,但是已经上线的app并分析崩溃报告就比较麻烦了。 之前我总是找到一个改一个,并靠别人测试重现来找出问题的地方,这样往往比较耗费时间。而且比较难找到原因的时候每次都是到网上找各种资源搜索,解决了之后也没有认真分析原因及收集,时间长了

fishmai的专栏 1531

iOS崩溃日志crash logs追踪以及调试方法

iOS崩溃日志crash logs追踪以及调试方法          在IOS程序开发和以及在真机运行程序时,经常会遇到程序crash的情况,从哪里可以获得crash的日志文件,以便更好的分析程序崩溃的原因,让应用更加完美。          在真机运行程序出现crash状况时,机器会自动产生log文件,它包含了在程序crash之前正在做什么的信息。在pc上对手机或者ipad设备进行同

1172

iOS应用的crash日志的分析基础

Outline 如何获得crash日志 如何解析crash日志 如何分析crash日志      1. iOS策略相关      2. 常见错误标识      3. 代码bug 一、如何获得crash日志 当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上。这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志

JasonLee的专栏 5万+

查看iOS Crash logs的方法(程序崩溃)

一、如何获得crash日志 当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上。这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志例外),对于开发人员定位问题很有帮助。 如果设备就在身边,可以连接设备,打开Xcode - Window - Devices,在左侧面板中选择你的设备  然后选择Device Logs(可

zhongmin_li的博客 1508

iOS崩溃调试的使用和技巧总结

在iOS开发调试过程中以及上线之后,程序经常会出现崩溃的问题。简单的崩溃还好说,复杂的崩溃就需要我们通过解析Crash文件来分析了,解析Crash文件在iOS开发中是比较常见的。 现在网上有很多关于解析崩溃信息的博客,但是大多质量参差不齐,或者有些细节没有注意到。今天写一篇博客总结一下我对崩溃调试的使用和技巧,如果有哪些错误或遗漏,还请指点,谢谢! 获取崩溃

Junyan_Jaya的博客 384
上一篇: AMR文件分析
下一篇: amr编码
JackHu
博客等级 码龄17年 4粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值