使用CFDictionarySetValue()将结构体存储为值

storing struct as value using CFDictionarySetValue()

本文关键字:存储 结构体 CFDictionarySetValue 使用      更新时间:2023-10-16

我刚开始使用Core Foundations。我想用字典来存储键值对。该值必须是指向结构体的指针。这个指针指向动态分配的缓冲区。

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地址:0x00000000000000110x00007fff8c9f339f in objc_msgSend_fixup ()

任何想法?

问题是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;
}