2013-03-07 41 views
2

Iam新使用Core Foundations。我想用字典來存儲一些關鍵值對。該值必須是一個指向結構體的指針。該指針指向動態分配的緩衝區。使用CFDictionarySetValue()存儲結構爲值()

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 0x00007fff8c9f339f在objc_msgSend_fixup()

任何想法?

+0

你有特殊原因不能使用,而不是核心基礎可可?這可以節省一些頭痛。 – Matthias 2013-03-07 08:00:24

+0

沒有這樣的東西,我剛開始使用CF,我的使用非常有限。這是唯一的用例。 – user2085689 2013-03-07 21:55:29

+0

有時需要CF。引用Apple:**重要:**使用CFDictionaryRef數據類型而非NSDictionary對象來跟蹤觸摸,因爲NSDictionary會複製其鍵。 UITouch類不採用對象複製所需的NSCopying協議。 – 2014-04-23 07:03:44

回答

3

問題是kCFTypeDictionaryValueCallBacks的說法。從文檔:當在CFDictionary的值是 所有CFType衍生對象

kCFTypeDictionaryValueCallBacks
預定義CFDictionaryValueCallBacks包含一組 結構回調適當使用。

所以你的情況,當值被添加到 字典,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; 
} 
+0

感謝Martin R爲縮小範圍。但是你的答案看起來像一個簡單的出路,將問題轉移到其他地方而不是解決問題。一個自定義的DictionaryValueCallBack會使引用計數保持活動狀態,並且可以舉出一個有效的例子嗎? – 2014-04-23 09:53:19

+0

或者,我可以推我的結構元素成CFArray,並使用kCFTypeDictionaryValueCallBack,畢竟? – 2014-04-23 09:58:52

+0

@PeterKämpf:問題是關於*「指向動態分配的緩衝區」的指針*,所以我認爲沒有可用的refcounting。當然,如果指針指向實現refcounting的東西(例如,COM接口),則可以提供相應的值回調。所以「一個有效的例子」取決於你想存儲什麼樣的指針。 - 首先將指針放入CFArray會引起問題,因爲它也使用CFArrayCallBacks參數。 – 2014-04-23 10:03:02