【问题标题】:Thread 1: EXC_BAD_ACCESS (code=13, address = 0x0)线程 1:EXC_BAD_ACCESS(代码 = 13,地址 = 0x0)
【发布时间】:2012-03-24 18:09:27
【问题描述】:

有一个程序可以编译,然后退出,返回上述错误信息。

这里是 0 objc_msgSend 日志;已将出现错误消息的行注释掉:

libobjc.A.dylib`objc_msgSend:
0x7fff8c9b7e80:  testq  %rdi, %rdi
0x7fff8c9b7e83:  je     0x00007fff8c9b7eb0       ; objc_msgSend + 48
0x7fff8c9b7e85:  testb  $1, %dil
0x7fff8c9b7e89:  jne    0x00007fff8c9b7ec7       ; objc_msgSend + 71
0x7fff8c9b7e8c:  movq   (%rdi), %r11
0x7fff8c9b7e8f:  pushq  %rax
0x7fff8c9b7e90:  movq   16(%r11), %r10
0x7fff8c9b7e94:  movl   %esi, %eax
0x7fff8c9b7e96:  andl   (%r10), %eax           // error message arrow appears on this line
0x7fff8c9b7e99:  movq   16(%r10,%rax,8), %r11
0x7fff8c9b7e9e:  incl   %eax
0x7fff8c9b7ea0:  testq  %r11, %r11
0x7fff8c9b7ea3:  je     0x00007fff8c9b7edb       ; objc_msgSend + 91
0x7fff8c9b7ea5:  cmpq   (%r11), %rsi
0x7fff8c9b7ea8:  jne    0x00007fff8c9b7e96       ; objc_msgSend + 22
0x7fff8c9b7eaa:  popq   %rax

// Rest left out; no error messages

main.m:

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

#import "Transaction.h"
#import "CashTransaction.h"
#import "CreditCardTransaction.h"

int main(int argc, const char * argv[])
{

    Budget *europeBudget = [Budget new];
    [europeBudget createBudget:1000.00 withExchangeRate:1.2500];

    Budget *englandBudget = [Budget new];
    [englandBudget createBudget:2000.00 withExchangeRate:1.5000];


    NSMutableArray *transactions = [[NSMutableArray alloc]initWithCapacity:10];
    Transaction *aTransaction;
    for (int n=1; n < 2; n++) {

        [aTransaction createTransaction:n * 100 forBudget:europeBudget];
        [transactions addObject:aTransaction];
        aTransaction = [CashTransaction new];
        [aTransaction createTransaction:n * 100 forBudget:englandBudget];
        [transactions addObject:aTransaction];
    }

    int n = 1;
    while (n < 4) {

        [aTransaction createTransaction:n * 100 forBudget:europeBudget];
        [transactions addObject:aTransaction];
        aTransaction = [CreditCardTransaction new];
        [aTransaction createTransaction:n * 100 forBudget:englandBudget];
        [transactions addObject:aTransaction];
        n++;
    }


        for (Transaction * aTransaction in transactions) {
            [aTransaction spend];
    }


            return 0;
}

事务.h

进口

@class 预算;

@interface Transaction : NSObject
{
    Budget *budget;
    double amount;
}

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget;
- (void) spend;
- (void)trackSpending: (double) theAmount;

@end

交易.m

#import "Transaction.h"
#import "Budget.h"

@implementation Transaction

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget
{
    budget = aBudget;
    amount = theAmount;
}

- (void) spend
{
    // Fill in the method in subclasses
}

-(void)trackSpending: (double) theAmount
{
    NSLog(@"You are about to spend another %.2f", theAmount);
}
@end

【问题讨论】:

  • 如果我错了,请纠正我,但 0x0 是 NULL 的十六进制。我认为您正在向空对象发送消息。
  • 以为它可能在 NSMutableArray 对象中,但找不到。已添加 main.m 文件供您阅读。
  • 向 nil 对象发送消息完全没问题。它返回零,编译器将其转换为函数的返回类型。 (如果您的返回类型是 NSRect 的话,那就是个问题,但我记得较新版本的 SDK 可以正确处理它。) objc_messageSend 中的崩溃通常意味着您正在向已释放的对象发送消息。

标签: objective-c xcode


【解决方案1】:

我在寻找解决 SIGSEGV 周围另一个问题的解决方案时遇到了这个问题。

虽然回复有点晚,但为了文档和完整性,我想回答这个问题。

出现问题是因为您在没有实例化对象的情况下向对象发送消息。

Transaction *aTransaction;
for (int n=1; n < 2; n++) {

    [aTransaction createTransaction:n * 100 forBudget:europeBudget];

并且创建方法被定义为:

- (void) createTransaction:(double)theAmount forBudget:(Budget*) aBudget;

我会写这些方法如下。

首先,createTransaction 对我来说听起来像是一种工厂方法。所以,我会把它变成一个类方法,比如:

+(Transaction *) createTransactionWithAmount:(double) theAmount forBudget: (Budget *) aBudget;

然后我会使用如下的工厂方法:

for (int n=1; n < 2; n++) {
     Transaction *aTransaction = [Transaction createTransactionWithAmount: n*100 forBudget: europeBudget];
   // [aTransaction createTransaction:n * 100 forBudget:europeBudget];
    [transactions addObject:aTransaction];

这应该可以解决代码的 2 个问题:

1) 您将始终有一个实例来发送消息,该实例定义为 aTransaction var
2) 您不必担心将此对象添加到集合中,因为它不再是 nil。

【讨论】:

    【解决方案2】:

    aTransaction 在声明时没有赋值,所以它以一个垃圾值开始。第一次通过循环时,您正在向该垃圾值发送一条消息:崩溃!用 nil 初始值声明变量将解决问题:

    Transaction *aTransaction = nil;
    

    【讨论】:

    • 问题:Transaction 类有两个实例变量:Budget 和 Amount。如果在 enum 函数中填充了默认 ivars,为什么会崩溃?我已添加 Transaction.h、.m 文件供您查看。将代码更改为“Transaction *aTransaction = nil;”但我撞车了。得到一个线程 1:在 [transactions addObject:aTransaction] 上发出信号 SIGABRT 消息;行
    • 我不确定您所说的“枚举函数”是什么意思。如果您正在初始化 aTransaction,我看不出代码中有任何明显错误。尝试打开 NSZombieEnabled(谷歌上的说明),看看它说了什么。
    • 抱歉延迟回复;我只是尝试从头开始再次编码,看看是否遇到相同的错误,我做到了。对于枚举函数,我指的是循环。开启 NSZombie Enabled 后会发现什么。
    • 已通过静态分析器运行它。表示消息表达式中的 Reeiver 是一个未初始化的值 [aTransaction createTransaction:n * 100 forBudget:europeBudget];当我将其更改为 Transaction *aTransaction = nil;我有一个线程 1:在 [transactions addObject:aTransaction] 上发出信号 SIGABRT;行。
    • @davehayden 如果这是 ARC 代码(我怀疑这是因为缺少释放调用),那么所有对象都会自动初始化为 nil。所以在ARC中,Transaction *aTransaction;Transaction *aTransaction = nil;是一样的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    • 2016-09-21
    相关资源
    最近更新 更多