【问题标题】:valueForKey: on packed struct?valueForKey:在打包结构上?
【发布时间】:2013-01-24 10:25:35
【问题描述】:

给定以下打包结构:

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" 字符串。 (我实际上想要实现的是递归打印对象内容)。

【问题讨论】:

  • "是苹果的bug吗?"这听起来很有可能。

标签: ios objective-c struct


【解决方案1】:

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

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

【讨论】:

  • “在这个时代,最好让编译器为你处理事情。” — 不幸的是我不能;)。我正在从/向网络获取/发送这些结构,因此它们应该被精细打包以匹配网络协议......
  • @ivanzoid 仅仅因为这是wire 上使用的数据结构,并不意味着您需要在程序中使用该结构。您应该使用编组将内部表示转换为外部表示,特别是如果您关心 endianness(移植到大端系统时会这样做)。
  • @trojanfoe 这将为我增加更多的工作:D 幸运的是我们的网络协议字节序匹配 iOS 字节序(所以,小字节序)
【解决方案2】:

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

你有没有尝试过改变

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

阅读

Foo boo = obj.foo;

?

Foo 不是也永远不会是idvalueForKey: 返回 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 中存在一个 ObjectNSObject 继承自。我认为这只是在您的示例中。

【讨论】:

  • “我敢打赌getValue: 是最糟糕的地方。” — 不,我真的什至不碰从valueForKey: 返回的对象。我已经更新了代码,现在是重现崩溃的完整代码(valueForKey: 部分可以从模板 iOS 项目中的viewDidLoad 调用)。
猜你喜欢
  • 1970-01-01
  • 2021-05-29
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 2018-08-13
  • 2017-10-16
相关资源
最近更新 更多