You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用g_hash_table_new_full存储post结构体时出现信息丢失问题求助

Troubleshooting Post Data Loss in GHashTable

Let’s break down why your post data might be disappearing when using GHashTable with g_hash_table_new_full, and walk through actionable fixes for each scenario.

1. Mismatched Hash/Equal Functions for 64-bit IDs

Your hash table uses g_int_hash and g_int_equal—these are built for 32-bit integer keys. But your post struct uses long id, which is 64 bits on most modern systems. This mismatch causes two critical issues:

  • Hash collisions: 64-bit IDs get truncated to 32 bits during hashing, so different IDs might map to the same bucket.
  • Failed lookups: g_int_equal only compares 32 bits of the ID, so valid lookups can return NULL even when the entry exists.

Fix:
Swap to 64-bit compatible hash and equality functions:

GHashTable* g_hash_table_posts = g_hash_table_new_full(
    g_int64_hash,    // Properly hashes 64-bit long values
    g_int64_equal,   // Completes full 64-bit comparisons
    NULL,
    &free_post
);

Ensure all insert/lookup operations use pointers to long (not int) values to match.

2. Invalid Memory Handling for Post Structs

Data loss often stems from bad memory management practices with your post structs:

  • Stack-allocated posts: If you insert a post that lives on the stack (not the heap), the memory gets overwritten once the stack frame exits. The hash table will hold a dangling pointer, leading to garbage data or "missing" entries.
  • Incomplete cleanup in free_post: If your cleanup function doesn’t free heap-allocated members like title and tags, you’ll get memory leaks—and if it frees the struct before its members, you’ll trigger undefined behavior that can corrupt the hash table.

Fixes:

  • Always allocate posts on the heap with g_malloc or malloc:
    struct post* new_post = g_malloc(sizeof(struct post));
    new_post->title = g_strdup("My First Post");
    new_post->tags = g_strdup("c,glib");
    // Initialize other fields (id, score, etc.)
    g_hash_table_insert(g_hash_table_posts, &new_post->id, new_post);
    
  • Update free_post to fully clean up all members:
    void free_post(gpointer data) {
        struct post* p = (struct post*)data;
        g_free(p->title);   // Free the heap-allocated title string
        g_free(p->tags);    // Free the tags string
        g_free(p);          // Free the post struct itself
    }
    

3. Duplicate ID Overwrites

GHashTable enforces unique keys. If you insert two posts with the same id, the second entry will overwrite the first—making it look like the original post vanished.

Fix:
Add a check before inserting to avoid overwrites:

if (!g_hash_table_contains(g_hash_table_posts, &new_post->id)) {
    g_hash_table_insert(g_hash_table_posts, &new_post->id, new_post);
} else {
    g_warning("Post with ID %ld already exists", new_post->id);
    free_post(new_post); // Prevent memory leaks from duplicate posts
}

If you need to store multiple posts per ID, adjust the hash table to map keys to GList instances (each list holds all posts for that ID):

GHashTable* g_hash_table_posts = g_hash_table_new_full(
    g_int64_hash, g_int64_equal,
    NULL,
    (GDestroyNotify)g_list_free_full // Frees the list and all posts in it
);

// Insert logic for multiple posts per ID
GList* post_list = g_hash_table_lookup(g_hash_table_posts, &new_post->id);
post_list = g_list_prepend(post_list, new_post);
g_hash_table_insert(g_hash_table_posts, &new_post->id, post_list);

4. Incorrect Lookup Logic

Sometimes data isn’t lost—it’s just not being found. Common lookup mistakes include:

  • Using an int pointer instead of a long pointer for the lookup key (mismatching the type expected by g_int64_equal).
  • Accidentally using parent_id or another field instead of id as the lookup key.

Fix:
Double-check your lookup code to ensure you’re passing the correct key type and value:

long target_id = 12345;
struct post* found_post = g_hash_table_lookup(g_hash_table_posts, &target_id);
if (found_post == NULL) {
    g_debug("Post with ID %ld could not be found", target_id);
}

5. Thread Safety Violations

If you’re accessing the hash table from multiple threads without synchronization, race conditions can corrupt the table’s internal structure—leading to missing entries, crashes, or garbage data. GHashTable is not thread-safe by default.

Fix:
Wrap all hash table operations (insert, lookup, delete) with a GMutex:

GMutex post_table_mutex;

// Initialize the mutex once at startup
g_mutex_init(&post_table_mutex);

// Example lookup with mutex protection
g_mutex_lock(&post_table_mutex);
struct post* found = g_hash_table_lookup(g_hash_table_posts, &target_id);
// Perform operations on the found post...
g_mutex_unlock(&post_table_mutex);

内容的提问来源于stack exchange,提问作者Pedro Lima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:45:01