【问题标题】:storing struct as value using CFDictionarySetValue()使用 CFDictionarySetValue() 将结构存储为值
【发布时间】:2013-03-07 06:50:25
【问题描述】:

我不熟悉使用核心基础。我想使用字典来存储一些键值对。该值必须是指向结构的指针。该指针指向动态分配的缓冲区。

CFMutableDictionaryRef init_hash_table() {

    return CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}

这用于创建字典并将返回值存储为全局变量。

CFNumberRef
create_hash_key(int sd) {
    return CFNumberCreate(NULL, kCFNumberIntType, &sd);
}


int
add_hash_entry(CFMutableDictionaryRef dict, int sd, void *pkt) {

    CFNumberRef key = create_hash_key(sd);

    CFDictionarySetValue(dict, key, pkt);
    return 0;
}

当我执行这段代码时,我得到了段错误。我看到 pkt 有一个有效的地址,并且似乎创建了密钥。有谁知道如何分配一个指向值部分的指针?

程序接收到信号EXC_BAD_ACCESS,无法访问内存。 原因:KERN_INVALID_ADDRESS 地址:0x0000000000000011 objc_msgSend_fixup()中的0x00007fff8c9f339f

有什么想法吗?

【问题讨论】:

  • 您是否有特定的理由不使用 Cocoa 而不是 Core Foundation?它可以避免一些头痛。
  • 没什么,我刚开始使用 CF,我对它的使用非常有限。这是唯一的用例。
  • 有时需要 CF。引用 Apple 的话:重要提示: 使用 CFDictionaryRef 数据类型而不是 NSDictionary 对象来跟踪触摸,因为 NSDictionary 复制它的键。 UITouch 类没有采用对象复制所需的 NSCopying 协议。

标签: c++ c core-foundation


【解决方案1】:

问题在于kCFTypeDictionaryValueCallBacks 参数。来自文档:

kCFTypeDictionaryValueCallBacks
预定义的CFDictionaryValueCallBacks 结构包含一组 当CFDictionary 中的值是 所有CFType 派生对象。

所以在你的情况下,当值被添加到指针时,CFRetain() 被调用 字典。这会导致崩溃,因为指针未指向 CoreFoundation 对象。

你可以创建字典

CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);

相反,不会对该值进行“引用计数”。

或者,您可以将指针包装成 CFDataRef 并将其放入 字典。

在这两种情况下,指针仍然有效是您的责任 稍后从字典中检索该值时。


这是一个简单示例,您可以如何为自定义对象实现引用计数:

typedef struct {
    int refcount;
    int val;
} mystruct;

const void *myretain(CFAllocatorRef allocator, const void *value)
{
    mystruct *p = (mystruct *)value;
    p->refcount++;
    return p;
}

void myrelease(CFAllocatorRef allocator, const void *value)
{
    mystruct *p = (mystruct *)value;
    if (p->refcount == 1)
        free(p);
    else
        p->refcount--;
}

int main(int argc, const char * argv[])
{
    mystruct *p = malloc(sizeof(*p));
    p->refcount = 1;
    p->val = 13;

    CFDictionaryValueCallBacks vcb = { 0 , myretain, myrelease, NULL, NULL };
    CFMutableDictionaryRef dict =  CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &vcb);

    int sd = 13;
    CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &sd);

    CFDictionarySetValue(dict, key, p);
    // refcount == 2
    myrelease(NULL, p);
    // refcount == 1

    mystruct *q = CFDictionaryGetValue(dict, key);
    // refcount is still 1, "GetValue" does not increment the refcount

    CFRelease(dict);
    // object is deallocated

    return 0;
}

【讨论】:

  • 感谢 Martin R 缩小范围。但是您的答案看起来很简单,将问题转移到其他地方而不是解决它。自定义 DictionaryValueCallBack 是否会保持引用计数处于活动状态,您能否举一个可行的示例?
  • 或者我可以将我的结构元素推入 CFArray 并使用 kCFTypeDictionaryValueCallBack,毕竟?
  • @PeterKämpf:问题是关于“指向动态分配的缓冲区”的指针,所以我假设没有可用的引用计数。当然,如果指针指向实现了引用计数的东西(例如 COM 接口),那么您可以提供相应的值回调。所以“一个有效的例子”取决于你想要存储什么样的指针。 - 首先将指针放入 CFArray 只会解决问题,因为这也使用了 CFArrayCallBacks 参数。
  • @PeterKämpf:我添加了一个非常简单的带有自定义引用计数的自定义值回调示例。
猜你喜欢
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 2017-07-09
  • 2017-09-15
相关资源
最近更新 更多