【问题标题】:Error in device but not in simulator设备错误但模拟器中没有
【发布时间】:2009-05-19 04:49:25
【问题描述】:

我有这行代码(splits是一个实例变量):

splits = [[NSMutableArray alloc] initWithObjects:[NSMutableArray array]];

这段代码显然是错误的(它应该是零终止的),但是它在模拟器中运行良好,即使它在设备上抛出了EXC_BAD_ACCESS。我的问题是模拟器为什么不报错?

凯尔

【问题讨论】:

    标签: iphone objective-c cocoa-touch


    【解决方案1】:

    实际结果取决于内存内容。模拟器上的内存布局很可能在第一个参数(匿名数组)的地址之后包含一个零。这个零被解释为好像你会用nil 关闭参数列表并且一切正常。 (P.S. 对于这种情况,有一个有趣的宏称为 NS_REQUIRES_NIL_TERMINATION,尽管它显然在这里没有帮助。)

    【讨论】:

      【解决方案2】:

      iPhone 的内存比您的计算机少得多。在被 initWithObjects 函数使用之前,堆栈的内存区域可能已设置为 0x00 (nil)。当参数被发送到 initWithObjects 函数并分配堆栈时,计算机上的内存空间比 iPhone 更可能预设为 0x00,因为相同的内存空间使用频率较低。所以很可能是从内存中已经设置为 0 的位置读取 nil。

      如果你在计算机上填满内存,然后运行模拟器,模拟器可能会像 iPhone 一样崩溃。

      【讨论】:

      • 计算机将清理已使用的内存,然后再将内存传递给模拟器等进程...如果进程向操作系统请求内存,而操作系统不清理将内存传递给请求进程之前的内存,这将是安全/隐私风险。
      【解决方案3】:

      缓冲区溢出会导致未定义的行为。不能保证它们会导致访问冲突(甚至是明显的错误)。在现代机器上,如果您碰巧踩到“别人的”内存,它们会导致访问冲突,但如果您只是从自己的堆栈中读取垃圾,则可能不会。

      基本上,你只需要小心,并且可以尝试像MudflapValgrind这样的工具来帮助你(这两个更适用于C/C++,我不知道它们的应用效果如何到 Obj-C)。

      【讨论】:

      • 我猜这并不完全是缓冲区溢出——负责获取参数的 va_arg 宏只是简单地跳过最后一个参数而不覆盖任何内容。
      • 我仍然认为它是缓冲区溢出。只是 /read/ 溢出了缓冲区的末尾,而不是 /write/。如果你想要技术,那就是 CWE-126,缓冲区过度读取 (cwe.mitre.org/data/definitions/126.html) 或 CWE-125,越界读取 (cwe.mitre.org/data/definitions/125.html)。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 2011-11-17
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      • 2018-09-13
      相关资源
      最近更新 更多