admin 管理员组

文章数量: 1184232

简介

GLib内存申请及释放函数。

数据结构

无特殊数据结构

函数列表

#define 	g_new()
#define 	g_new0()
#define 	g_renew()
#define 	g_try_new()
#define 	g_try_new0()
#define 	g_try_renew()
gpointer 	g_malloc ()
gpointer 	g_malloc0 ()
gpointer 	g_realloc ()
gpointer 	g_try_malloc ()
gpointer 	g_try_malloc0 ()
gpointer 	g_try_realloc ()
gpointer 	g_malloc_n ()
gpointer 	g_malloc0_n ()
gpointer 	g_realloc_n ()
gpointer 	g_try_malloc_n ()
gpointer 	g_try_malloc0_n ()
gpointer 	g_try_realloc_n ()
void 	g_free ()
void 	g_clear_pointer ()
gpointer 	g_steal_pointer ()
#define 	g_alloca()
#define 	g_newa()
#define 	g_memmove()
gpointer 	g_memdup ()
void 	g_mem_set_vtable ()
gboolean 	g_mem_is_system_malloc ()
void 	g_mem_profile ()

函数功能分类

本章函数按功能大致分为内存申请、内存释放、内存拷贝及其他,还有一些已经过时的不再使用的函数。

内存申请

// g_new和g_new0的区别:g_new0将新申请的内存置为0。
// g_new0使用更广泛。
#define	g_new()
#define	g_new0()

// 重新申请内存,内存首地址不变
#define	g_renew()
// 尝试申请内存,如果申请失败,不会退出程序,只会返回失败
#define	g_try_new()
#define	g_try_new0()
#define	g_try_renew()

// 同malloc和realloc,g_malloc0最常用,会将新申请的内存置为0
gpointer	g_malloc ()
gpointer	g_malloc0 ()
gpointer	g_realloc ()

// 与malloc类似,但只会返回失败,不退出程序
gpointer	g_try_malloc ()
gpointer	g_try_malloc0 ()
gpointer	g_try_realloc ()

// 带_n的是按块申请,可以申请多个块,总长度为每块大小乘以块数。
gpointer	g_malloc_n ()
gpointer	g_malloc0_n ()
gpointer	g_realloc_n ()
gpointer	g_try_malloc_n ()
gpointer	g_try_malloc0_n ()
gpointer	g_try_realloc_n ()

// 同alloca,较复杂,不好控制,不提倡使用
#define	g_alloca()
#define	g_newa()

释放

// 内存释放,g_new和g_malloc都可以使用g_free释放。
void	g_free ()

清空内存

// 置空一个指针,传入自定义释放函数释放指针指向的内存。
// 如果是一个结构体,结构体内又有数据,这种释放方式将会非常便捷。
void	g_clear_pointer ()

// 拷贝

gpointer	g_memdup ()

其他

// 转移指针指向内存的所有权,内存不会被释放
gpointer	g_steal_pointer ()

// 一些过时的函数,不能再使用

#define	g_memmove()
void	g_mem_set_vtable ()
gboolean	g_mem_is_system_malloc ()
void	g_mem_profile ()

函数功能说明及综合演示

内存申请及释放

示例代码如下:
源码见glib_examples\glib_mem_alloc\glib_mem_alloc_basic

#include <glib.h>

typedef struct my_data_t {
    gint id;
    gchar *name;
}my_data;

gint main(gint argc, gchar **argv)
{
    gint *ids = NULL;
    gchar *str = NULL;
    my_data *d = NULL;

    gint i = 0;

    ids = g_new(gint, 4);
    g_return_val_if_fail(ids, -1);
    for(i=0;i<4;i++) {
        ids[i] = i+100;
    }

    str = g_new0(gchar, 8);
    g_return_val_if_fail(str, -1);
    g_strlcpy(str, "abcdef", 8);

    d = g_new0(my_data, 1);
    g_return_val_if_fail(d, -1);
    d->id = 100;
    d->name = g_strdup("abcd");

    g_print("ids: [%d] [%d] [%d] [%d] \n", ids[0], ids[1], ids[2], ids[3]);
    g_print("str: %s \n", str);
    g_print("d->id:%d, d->name:%s \n", d->id, d->name);
    

    g_free(ids);
    g_free(str);
    g_free(d->name);
    g_free(d);

    return 0;
}

运行结果:

[root@centos7_6 build]# ./glib_mem_alloc_basic
ids: [100] [101] [102] [103]
str: abcdef
d->id:100, d->name:abcd

上面程序使用g_new和g_new0申请了一个指针数组、一个字符串和一个结构体。使用valgrind检查无内存泄露。

[root@centos7_6 build]# valgrind --tool=memcheck --leak-check=full ./glib_mem_alloc_basic
==51417== Memcheck, a memory error detector
==51417== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==51417== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==51417== Command: ./glib_mem_alloc_basic
==51417==
ids: [100] [101] [102] [103]
str: abcdef
d->id:100, d->name:abcd
==51417==
==51417== HEAP SUMMARY:
==51417==     in use at exit: 18,662 bytes in 10 blocks
==51417==   total heap usage: 34 allocs, 24 frees, 118,679 bytes allocated
==51417==
==51417== LEAK SUMMARY:
==51417==    definitely lost: 0 bytes in 0 blocks
==51417==    indirectly lost: 0 bytes in 0 blocks
==51417==      possibly lost: 0 bytes in 0 blocks
==51417==    still reachable: 18,662 bytes in 10 blocks
==51417==         suppressed: 0 bytes in 0 blocks
==51417== Reachable blocks (those to which a pointer was found) are not shown.
==51417== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==51417==
==51417== For counts of detected and suppressed errors, rerun with: -v
==51417== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
[root@centos7_6 build]#
清空指针指向的内存

当结构体比较复杂,其内部包含指针,指针又包含新的不连续内存或者新的结构体等等嵌套情形时,如果想释放结构体,将会稍显棘手。GLib提供了一种巧妙的清空指针的方式,结构体变量释放函数由用户自己指定。这就是清空指针指向的内存。
示例代码如下:
源码见glib_examples\glib_mem_alloc\glib_mem_alloc_clear_prt

#include <glib.h>

typedef struct my_data {
    gint id;
    gchar *name;
    gchar *memo;
}my_data_t;

void my_data_destroy_func(gpointer data)
{
    my_data_t *d = (my_data_t *)data;
    g_return_if_fail(d);

    if(NULL != d->name) {
        g_free(d->name);
    }

    if(NULL != d->memo) {
        g_free(d->memo);
    }

    g_free(d);
}

gint main(gint argc, gchar **argv)
{
    my_data_t *d = NULL;

    d = g_new0(my_data_t, 1);
    g_return_val_if_fail(d, -1);

    d->id = 100;
    d->name = g_strdup("abcd");
    d->memo = g_strdup("the memo info");

    g_print("d->id:%d, d->name:%s, d->memo:%s \n", d->id, d->name, d->memo);
    
    //g_free(d->name);
    //g_free(d->memo);
    //g_free(d);
    g_clear_pointer(&d, my_data_destroy_func);

    return 0;
}

运行结果:

[root@centos7_6 build]# ./glib_mem_alloc_clear_ptr
d->id:100, d->name:abcd, d->memo:the memo info

可以看到,比单独使用g_free函数释放结构体,更加便捷。
使用valgrind检查,发现并无内存泄露。

[root@centos7_6 build]# valgrind --tool=memcheck --leak-check=full ./glib_mem_alloc_clear_ptr
==53397== Memcheck, a memory error detector
==53397== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==53397== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==53397== Command: ./glib_mem_alloc_clear_ptr
==53397==
d->id:100, d->name:abcd, d->memo:the memo info
==53397==
==53397== HEAP SUMMARY:
==53397==     in use at exit: 18,662 bytes in 10 blocks
==53397==   total heap usage: 21 allocs, 11 frees, 52,475 bytes allocated
==53397==
==53397== LEAK SUMMARY:
==53397==    definitely lost: 0 bytes in 0 blocks
==53397==    indirectly lost: 0 bytes in 0 blocks
==53397==      possibly lost: 0 bytes in 0 blocks
==53397==    still reachable: 18,662 bytes in 10 blocks
==53397==         suppressed: 0 bytes in 0 blocks
==53397== Reachable blocks (those to which a pointer was found) are not shown.
==53397== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==53397==
==53397== For counts of detected and suppressed errors, rerun with: -v
==53397== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

本文标签: 入门 内存 09GLib