You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用[stringWithFormat:]创建NSString时触发EXC_BAD_ACCESS错误的技术求助

排查NSString stringWithFormat:触发EXC_BAD_ACCESS的问题

从你的堆栈追踪和代码来看,这个崩溃发生在stringWithFormat:内部的__CFStringAppendFormatCore方法中,最终调用objc_opt_respondsToSelector时出错——这通常意味着你传给stringWithFormat:的某个参数是无效的Objective-C对象指针(比如野指针、已释放的对象,或者根本不是NSString类型的指针)。

结合你的代码[[NSString stringWithFormat:@"%@/%@/%@",UserLibrary,PREFERENCE_PLIST_DIR_NAME,PREFERENCE_PLIST_NAME] stringByExpandingTildeInPath];,我们可以从以下几个方向排查:

1. 检查UserLibrary的有效性

UserLibrary是普通的NSString*类型,最容易出现的问题是:

  • 它是一个野指针:比如指向了已经被释放的内存(ARC下可能是弱引用对象被销毁,MRC下可能是过度释放)
  • 它根本不是有效的NSString对象:比如被错误赋值为nil之外的无效地址

排查&解决方法:

  • 在GetPlistPath方法开头加调试日志,直接打印UserLibrary的地址和值:
    NSString* GetPlistPath(){
        NSLog(@"UserLibrary addr: %p, value: %@", UserLibrary, UserLibrary);
        return [[NSString stringWithFormat:@"%@/%@/%@",UserLibrary,PREFERENCE_PLIST_DIR_NAME,PREFERENCE_PLIST_NAME] stringByExpandingTildeInPath];
    }
    
    如果这行日志就崩溃,说明UserLibrary肯定有问题。
  • 确保UserLibrary的来源可靠:如果是获取用户Library目录,建议直接用系统API生成,避免手动持有指针的内存问题:
    NSString *UserLibrary = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
    
  • ARC环境下检查UserLibrary的引用类型:如果是__weak修饰的变量,改成__strong,确保对象不会被提前释放;MRC环境下要确保使用前调用过retain,或者它是全局/静态变量。

2. 检查常量宏的定义是否正确

PREFERENCE_PLIST_DIR_NAME和PREFERENCE_PLIST_NAME是NSString* const类型,但如果定义错误,也会导致崩溃:

  • 错误示例1:用#define定义成了C字符串(没有加@):
    #define PREFERENCE_PLIST_DIR_NAME "Preferences" // 这是const char*,不是NSString*
    
    传给%@格式化符时,系统会把它当成Objective-C对象去调用respondsToSelector,直接触发崩溃。
  • 错误示例2:常量没有被正确初始化,比如声明了但没赋值:
    NSString* const PREFERENCE_PLIST_DIR_NAME; // 未初始化,指向随机地址
    

排查&解决方法:

  • 确保常量的定义是正确的Objective-C字符串:
    NSString* const PREFERENCE_PLIST_DIR_NAME = @"Preferences";
    NSString* const PREFERENCE_PLIST_NAME = @"AppSettings.plist";
    
  • 如果用#define,要加上@,并且确保类型匹配:
    #define PREFERENCE_PLIST_DIR_NAME @"Preferences"
    

3. 开启僵尸对象调试(进阶技巧)

在Xcode中开启Zombie Objects诊断,可以更精准地定位是哪个对象被过度释放:

  1. 打开项目的Scheme(点击Xcode顶部的项目名→Edit Scheme)
  2. 切换到Run→Diagnostics选项卡
  3. 勾选Zombie Objects
  4. 重新运行程序,崩溃时会给出明确的提示,告诉你哪个已释放的对象被再次访问。

内容的提问来源于stack exchange,提问作者Monika Nainwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 12:42:37