4

给定以下打包结构:

typedef struct __attribute__((packed)) {
    BOOL flag;
    int x;
} Foo;

以及以下课程:

@interface Obj : NSObject
@property (nonatomic) Foo foo;
@end

@implementation Obj
@end

尝试调用valueForKey:具有打包结构类型的属性:

Obj *obj = [Obj new];
id boo = [obj valueForKey:@"foo"];

导致内部崩溃valueForKey:(实际上它不是在内部valueForKey:而是在随机位置崩溃,具体取决于月球大小,我猜这是内存损坏)。

如果我删除__attribute__((packed))它工作正常。有没有可能在不崩溃的情况下获取结构的数据?是苹果的bug吗?

PS。我确实需要在运行时这样做,即我不能直接调用.foo,我在运行时只有@"foo"字符串。(我实际上想要实现的是递归打印对象内容)。

4

2 回答 2

0

在您的用例中避​​免使用 KVO,并坚持使用方便的花花公子<objc/runtime.h>标题。您可以使用这种自省来重新实现 KVO 的基本部分。结构打包主要用于确保编译器没有正确对齐内部字段,因此 CPU 在执行期间不需要在硬件级别处理它。在这个时代,最好让编译器为你处理事情。

如果您真的更喜欢这种结构打包(如您所说,在网络传输场景中),我将需要更多信息来确定问题所在。也许尝试更改@property (nonatomic) Foo foo;@property (nonatomic) NSValue *foo;然后将其装箱并自己拆箱?这样,异常/错误将在您的应用程序的域中。

于 2013-02-08T15:55:09.077 回答
0

我不知道这是否可以通过属性实现,但如果可以,我认为您使用的语法不正确。

你试过改变

id boo = [obj valueForKey:@"foo"]; 

读书

Foo boo = obj.foo;

?

Foo 不是也永远不会是id. valueForKey:返回 id,并且运行时可能会试图struct Foo挤进NSValue.

如果您valueForKey:出于某种原因需要使用,您的访问权限需要看起来像。

Foo myFoo = FooFactory();
Object *myObj = [Object new];
[myObj setValue:@( myFoo ) forKey:@"foo"];

Foo myFooOut;
[[myObj valueForKey:@"foo"] getValue:&myFooOut];
//I bet `getValue:` is where things are barfing.

在这种情况下,如果NSValue' 的机器确实无法处理打包的结构,您只需要以老式的方式编写访问器:-<key>和 -set:`。

PS:永远不要将类命名为“对象”,实际上Object在某些 SDK 中有一个NSObject继承自。我假设这只是在你的例子中。

于 2013-02-08T17:15:02.543 回答