C - Valgrind发现内存泄漏,但它不应该有

时间:2017-05-18 16:11:12

标签: c memory-leaks

几天后,我一直在尝试清理系统中的内存泄漏。但这一次内存泄漏一直困扰着我。

问题:Valgrind报告内存泄漏:

==28423== 10,988 (2,624 direct, 8,364 indirect) bytes in 82 blocks are definitely lost in loss record 405 of 409
==28423==    at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28423==    by 0x5553780: g_malloc0 (in /lib/x86_64-linux-gnu/libglib-2.0.so.0.4800.1)
==28423==    by 0x1B432E56: janus_audiobridge_create_user_secret (janus_audiobridge_room_helper.c:641)
==28423==    by 0x1B4250B3: janus_audiobridge_init (janus_audiobridge.c:281)
==28423==    by 0x4111BF: main (janus.c:3898)

Heres janus_audiobridge_create_user_secret (janus_audiobridge_room_helper.c:641):

method_user_secret_error_case *janus_audiobridge_create_user_secret(PGconn *conn, janus_audiobridge_user_secret_model *user_secret_model, gboolean insert_in_db) {
    JANUS_LOG(LOG_VERB, "Creating user_secret\n");

    /* Create the audio bridge secret */
    janus_audiobridge_user_secret *user_secret = g_malloc0(sizeof(janus_audiobridge_user_secret));
    method_user_secret_error_case *error = g_malloc0(sizeof(method_user_secret_error_case));
    if (user_secret_model->user_secret) {
        user_secret->user_secret = g_strdup(user_secret_model->user_secret);
    } else {
        gchar *new_secret = randstring((size_t)100);
        user_secret->user_secret = g_strdup(new_secret);
        user_secret_model->user_secret = g_strdup(new_secret); // Model is necesarry for saving to database
        g_free(new_secret);
    }
    user_secret->user_ip = g_strdup(user_secret_model->user_ip);
    user_secret->created_at = user_secret_model->created_at;
    if (insert_in_db) {
        // Save to db
        int save_err = janus_audiobridge_create_user_secret_db(conn, user_secret_model);
        if (save_err == 0) {
            JANUS_LOG(LOG_ERR, "Failed to save to database.\n");
            g_free(user_secret->user_secret);
            g_free(user_secret->user_ip);
            g_free(user_secret);
            const gchar *error_message = "Error saving to database.\n";
            error->error = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
            error->error_message = error_message;
            return error;  
        }
    }

    g_hash_table_insert(user_secrets, g_strdup(user_secret->user_secret), user_secret);
    // Prepare response
    const gchar *error_message = "";
    error->error = 0;
    error->error_message = error_message;
    error->user_secret = user_secret;

    return error;
}

当然janus_audiobridge_init (janus_audiobridge.c:281)

/* Fetch all user_secrets from database */  
const gchar *select_all_user_secrets_query = "SELECT * FROM user_secrets;";
GHashTable *user_secrets_db = user_secrets_query(conn, select_all_user_secrets_query);
// Create user secrets from database
g_hash_table_iter_init(&iter, user_secrets_db);
while (g_hash_table_iter_next(&iter, NULL, &value)) {
    janus_audiobridge_user_secret_model *db_user_secret = value;
    method_user_secret_error_case *create_resp = janus_audiobridge_create_user_secret(conn, db_user_secret, (gboolean)FALSE);
    if (create_resp->error != 0) {
        JANUS_LOG(LOG_ERR, "Error: %s\n", create_resp->error_message); 
    }

    g_free(db_user_secret->user_secret);
    g_free(db_user_secret->user_ip);
    g_free(db_user_secret);
    g_free(create_resp);
}
// Free the hashtable of entries from database
g_hash_table_destroy(user_secrets_db);

所以我的问题是:为什么valgrind表明我甚至会泄漏记忆,我正在用g_free释放它?另一个user_secret结构存储在HashTable中,所以我无法释放它,因为我以后会使用它。

P.S我此时不会在代码的任何地方释放user_secret,因为我在系统的生命周期中始终如一地使用它。

谢谢!

编辑: 对不起,我忘了提供它是哪一行: 641行是 -

janus_audiobridge_user_secret *user_secret = g_malloc0(sizeof(janus_audiobridge_user_secret));

和281:

method_user_secret_error_case *create_resp = janus_audiobridge_create_user_secret(conn, db_user_secret, (gboolean)FALSE);

1 个答案:

答案 0 :(得分:0)

感谢@SiggiSv,@ n.m和@Attie

在释放janus_destroy上的用户机密后,valgrind停止报告内存泄漏。所以这对我来说更不是一个问题,不知道valgrind是如何工作的。再次感谢所有帮助过的人。

这是代码,如果有人发现它有用:

  // Free user secret memory - So Valgrind Doesn't register memory leak
  // We do this, because we don't delete user secret in janus logic, and valgrind sees that as a memory leak
    GHashTableIter iter;
    gpointer value;
    g_hash_table_iter_init(&iter, user_secrets);
    while (g_hash_table_iter_next(&iter, NULL, &value)) {
        janus_audiobridge_user_secret *user_secret = value;
        g_free(user_secret->user_secret);
        g_free(user_secret->user_ip);
        g_free(user_secret);
    }
    g_hash_table_destroy(user_secrets);
相关问题