在未初始化的对象上调用方法(空指针)

发布于 2024-08-30 03:53:46 字数 882 浏览 8 评论 0 原文

  1. 如果你在一个为零的对象(指针)上调用一个方法(可能是因为有人忘记初始化它),Objective-C 中的正常行为是什么?它不应该产生某种错误(分段错误、空指针异常...)吗?
  2. 如果这是正常行为,是否有办法改变这种行为(通过配置编译器)以便程序在运行时引发某种错误/异常?

为了更清楚我在说什么,这里有一个例子。

拥有这个类:

@interface Person : NSObject {

    NSString *name;

}

@property (nonatomic, retain) NSString *name;

- (void)sayHi;

@end

通过这个实现:

@implementation Person

@synthesize name;

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

- (void)sayHi {
    NSLog(@"Hello");
    NSLog(@"My name is %@.", name);
}

@end

在程序的某个地方我这样做:

Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike";            // shouldn't I get an error here?
[person sayHi];                   // and here
[person release];                 // and here
  1. What is the normal behavior in Objective-C if you call a method on an object (pointer) that is nil (maybe because someone forgot to initialize it)? Shouldn't it generate some kind of an error (segmentation fault, null pointer exception...)?
  2. If this is normal behavior, is there a way of changing this behavior (by configuring the compiler) so that the program raises some kind of error / exception at runtime?

To make it more clear what I am talking about, here's an example.

Having this class:

@interface Person : NSObject {

    NSString *name;

}

@property (nonatomic, retain) NSString *name;

- (void)sayHi;

@end

with this implementation:

@implementation Person

@synthesize name;

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

- (void)sayHi {
    NSLog(@"Hello");
    NSLog(@"My name is %@.", name);
}

@end

Somewhere in the program I do this:

Person *person = nil;
//person = [[Person alloc] init]; // let's say I comment this line
person.name = @"Mike";            // shouldn't I get an error here?
[person sayHi];                   // and here
[person release];                 // and here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏花。依旧 2024-09-06 03:53:46

发送到 nil 对象的消息在 Objective-C 中是完全可以接受的,它被视为无操作。无法将其标记为错误,因为它不是错误,事实上它可能是该语言的一个非常有用的功能。

来自文档

向 nil 发送消息

在 Objective-C 中,发送
消息为零——它根本没有任何效果
在运行时。有几种模式
在可可中利用这一点
事实。从 a 返回的值
发送给 nil 的消息也可能有效:

  • 如果该方法返回一个对象,则发送到 nil 的消息将返回
    0 (nil),例如:

    人 *motherInLaw = [[aPerson 配偶] 母亲];

    如果aPersonspousenil
    然后 mother 被发送到 nil 并且
    方法返回nil

  • 如果该方法返回任何指针类型,则任何大小小于的整数标量
    大于或等于sizeof(void*),a
    floatdoublelong double
    long long,然后发送一条消息
    nil返回0

  • 如果该方法返回一个 struct,如 Mac OS X ABI 所定义
    返回的函数调用指南
    注册,然后一条消息发送到
    nil 为每个字段返回 0.0
    数据结构。其他结构
    数据类型不会被填充
    零。

  • 如果该方法返回除上述值之外的任何值
    输入消息的返回值
    发送到 nil 是未定义的。

A message sent to a nil object is perfectly acceptable in Objective-C, it's treated as a no-op. There is no way to flag it as an error because it's not an error, in fact it can be a very useful feature of the language.

From the docs:

Sending Messages to nil

In Objective-C, it is valid to send a
message to nil—it simply has no effect
at runtime. There are several patterns
in Cocoa that take advantage of this
fact. The value returned from a
message to nil may also be valid:

  • If the method returns an object, then a message sent to nil returns
    0 (nil), for example:

    Person *motherInLaw = [[aPerson spouse] mother];

    If aPerson’s spouse is nil,
    then mother is sent to nil and the
    method returns nil.

  • If the method returns any pointer type, any integer scalar of size less
    than or equal to sizeof(void*), a
    float, a double, a long double,
    or a long long, then a message sent
    to nil returns 0.

  • If the method returns a struct, as defined by the Mac OS X ABI
    Function Call Guide to be returned in
    registers, then a message sent to
    nil returns 0.0 for every field in
    the data structure. Other struct
    data types will not be filled with
    zeros.

  • If the method returns anything other than the aforementioned value
    types the return value of a message
    sent to nil is undefined.

相对绾红妆 2024-09-06 03:53:46

来自 Greg Parker站点

如果运行 LLVM 编译器 3.0 (Xcode 4.2) 或更高版本

Messages to nil with return type | return
Integers up to 64 bits           | 0
Floating-point up to long double | 0.0
Pointers                         | nil
Structs                          | {0}
Any _Complex type                | {0, 0}

From Greg Parker's site:

If running LLVM Compiler 3.0 (Xcode 4.2) or later

Messages to nil with return type | return
Integers up to 64 bits           | 0
Floating-point up to long double | 0.0
Pointers                         | nil
Structs                          | {0}
Any _Complex type                | {0, 0}
逆蝶 2024-09-06 03:53:46

您应该清楚的一件事是,在 Objective-C 中,您不是在对象上调用方法,而是向对象发送消息。运行时将找到该方法并调用它。

自 Objective-C 的第一个版本以来,nil 消息始终是返回 nil 的安全无操作。有很多代码依赖于这种行为。

One thing you should be clear on is that in Objective-C, you don't call a method on an object, you send a message to an object. The runtime will find the method and call it.

Since the first versions of Objective-C, a message to nil has always been a safe no-op that returns nil. There's a lot of code that depends on this behavior.

静待花开 2024-09-06 03:53:46

什么也没发生。当你向nil发送消息时,意味着没有接收者
然后消息就飞走了。 objc_msgSend 方法是从 Runtime 库使用的。使用了消息调度机制,这就是为什么Objective-C有所不同,基于这个原理有很多优点。它不会像 Java 或 Swift 那样抛出任何错误

Nothing happened. When you send a message to nil it means that there is no receiver
and the message fly away. objc_msgSend method is used from Runtime library. Message dispatch mechanism is used that is why Objective-C is different and there are a lot of advantages are based on this principle. It will not throws any errors as Java or Swift do

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文