Memory management 删除Vala中的GLib.Tree元素时指针无效

Memory management 删除Vala中的GLib.Tree元素时指针无效,memory-management,glib,vala,Memory Management,Glib,Vala,此代码导致以下错误 free():指针无效 使用GLib; 使用油嘴滑舌。随机; //全局变量 主树; 公共静态int main(字符串[]args){ //启动随机种子 Random.set_seed((uint32)get_单调_time()); //主目录树初始化 mainTree=new Tree.full(mainTreeCompareDataFunction,free,free); //循环的随机大小 对于(int i=0;i{ mainTree.remove(mainTreeKe

此代码导致以下错误

free():指针无效

使用GLib;
使用油嘴滑舌。随机;
//全局变量
主树;
公共静态int main(字符串[]args){
//启动随机种子
Random.set_seed((uint32)get_单调_time());
//主目录树初始化
mainTree=new Tree.full(mainTreeCompareDataFunction,free,free);
//循环的随机大小
对于(int i=0;i{
mainTree.remove(mainTreeKey);//此行导致free():无效指针错误
返回false;
});
返回0;
}
公共字符串randomString(){
string charset=“abcdefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyz”;
字符串stringToReturn=“”;
//创建一个随机的8字符字符串
对于(int i=0;i<8;i++){
stringToReturn+=charset[int_range(0,charset.length)]。到_字符串();
}
返回字符串返回;
}
公共int树嵌套比较数据函数(int a、int b){
如果(ab)返回1;
返回0;
}
public int mainTreeCompareDataFunction(字符串a、字符串b){
返回strcmp(a,b);
}
我怀疑这是因为树中有一个嵌套的
GLib.Tree
,并且
free()
不能用于这些对象。如果我对
mainTree
的值使用
null
而不是destroy函数,则不会发生崩溃,但是如果我要重用
mainTree
变量,就会产生内存泄漏


有没有办法清空树并释放内存?

找到了解决方案,即手动管理内存。首先,使嵌套树成为指针。其次,将
null
传递给用于指定释放嵌套树的函数的参数。第三,将
null
传递给用于指定释放嵌套树的
int
键的函数的参数。最后,在清空主树时,使用
delete
关键字减少对嵌套树的引用

由于手动调用
delete
(此处特别调用
g_tree\u unref
)在Vala生成的C代码中,对嵌套树的引用将在此代码中降至0,因此嵌套树的所有键和值将被销毁,树分配的所有内存将被释放。这样就不会再发生无效指针错误,也不会出现内存泄漏

using GLib;
using GLib.Random;

// Global variable
Tree<string, Tree<int, string>* > mainTree;

public static int main (string[] args) {
    // Initiate random seed
    Random.set_seed ((uint32) get_monotonic_time());
    // mainTree initialization
    mainTree = new Tree<string, Tree<int, string> >.full (mainTreeCompareDataFunction, free, null);
    // Random sized for loop
    for (int i = 0; i < int_range (1000, 10001); i++) {
        // If a condition is met (i is even)
        if (i % 2 == 0) {
            // Create a Tree to nest onto mainTree
            Tree<int, string>* treeToNest = new Tree<int, string>.full (treeToNestCompareDataFunction, null, free);
            // Insert random content into treeToNest
            treeToNest->insert (int_range (0, 101), randomString ());
            // Insert the tree onto mainTree
            mainTree.insert (randomString (), treeToNest);
        }
    }

    // Empty the tree
    mainTree.@foreach ((mainTreeKey, mainTreeValue) => {
        delete mainTree.lookup (mainTreeKey);
        mainTree.remove (mainTreeKey);
        return false;
    });

    return 0;
}

public string randomString () {
    string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    string stringToReturn = "";
    // Create a random 8 character string
    for (int i = 0; i < 8; i++) {
        stringToReturn += charset[int_range (0, charset.length)].to_string ();
    }
    return stringToReturn;
}

public int treeToNestCompareDataFunction (int a, int b) {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0; 
}

public int mainTreeCompareDataFunction (string a, string b) {
    return strcmp (a, b);
}
使用GLib;
使用油嘴滑舌。随机;
//全局变量
主树;
公共静态int main(字符串[]args){
//启动随机种子
Random.set_seed((uint32)get_单调_time());
//主目录树初始化
mainTree=new Tree.full(mainTreeCompareDataFunction,free,null);
//循环的随机大小
对于(int i=0;i插入(int_范围(0,101),随机字符串());
//将树插入mainTree
mainTree.insert(randomString(),treeToNest);
}
}
//把树倒空
mainTree@foreach((mainTreeKey,mainTreeValue)=>{
删除mainTree.lookup(mainTreeKey);
mainTree.remove(mainTreeKey);
返回false;
});
返回0;
}
公共字符串randomString(){
string charset=“abcdefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyz”;
字符串stringToReturn=“”;
//创建一个随机的8字符字符串
对于(int i=0;i<8;i++){
stringToReturn+=charset[int_range(0,charset.length)]。到_字符串();
}
返回字符串返回;
}
公共int树嵌套比较数据函数(int a、int b){
如果(ab)返回1;
返回0;
}
public int mainTreeCompareDataFunction(字符串a、字符串b){
返回strcmp(a,b);
}
资料来源:


您可以编写lambda,该lambda将使用所有权转移删除子树

    mainTree = new Tree<string, Tree<int, string> >.full (mainTreeCompareDataFunction, free,
        (data) => {
          var tree = (Tree<string, Tree<int, string>>) data;
          // Ownership is transfered to this local var which calls unref when it goes out of scope
          var tree2 = (owned) tree;
        });
mainTree=new Tree.full(mainTreeCompareDataFunction,free,
(数据)=>{
变量树=(树)数据;
//所有权被转移到这个本地var,当它超出范围时调用unref
var tree2=(拥有的)树;
});
以下是完整的代码:

using GLib;
using GLib.Random;

// Global variable
Tree<string, Tree<int, string> > mainTree;

public static int main (string[] args) {
    // Initiate random seed
    Random.set_seed ((uint32) get_monotonic_time());
    // mainTree initialization
    mainTree = new Tree<string, Tree<int, string> >.full (mainTreeCompareDataFunction, free,
        (data) => {
          var tree = (Tree<string, Tree<int, string>>) data;
          // Ownership is transfered to this local var which calls unref when it goes out of scope
          var tree2 = (owned) tree;
        });
    // Random sized for loop
    for (int i = 0; i < int_range (1000, 10001); i++) {
        // If a condition is met (i is even)
        if (i % 2 == 0) {
            // Create a Tree to nest onto mainTree
            Tree<int, string> treeToNest = new Tree<int, string>.full (treeToNestCompareDataFunction, null, free);
            // Insert random content into treeToNest
            treeToNest.insert (int_range (0, 101), randomString ());
            // Insert the tree onto mainTree
            mainTree.insert (randomString (), treeToNest);
        }
    }

    // Empty the tree
    mainTree.@foreach ((mainTreeKey, mainTreeValue) => {
        mainTree.remove (mainTreeKey);
        return false;
    });

    return 0;
}

public string randomString () {
    string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    string stringToReturn = "";
    // Create a random 8 character string
    for (int i = 0; i < 8; i++) {
        stringToReturn += charset[int_range (0, charset.length)].to_string ();
    }
    return stringToReturn;
}

public int treeToNestCompareDataFunction (int a, int b) {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0; 
}

public int mainTreeCompareDataFunction (string a, string b) {
    return strcmp (a, b);
}
使用GLib;
使用油嘴滑舌。随机;
//全局变量
主树;
公共静态int main(字符串[]args){
//启动随机种子
Random.set_seed((uint32)get_单调_time());
//主目录树初始化
mainTree=new Tree.full(mainTreeCompareDataFunction,free,
(数据)=>{
变量树=(树)数据;
//所有权被转移到这个本地var,当它超出范围时调用unref
var tree2=(拥有的)树;
});
//循环的随机大小
对于(int i=0;iusing GLib;
using GLib.Random;

// Global variable
Tree<string, Tree<int, string> > mainTree;

public static int main (string[] args) {
    // Initiate random seed
    Random.set_seed ((uint32) get_monotonic_time());
    // mainTree initialization
    mainTree = new Tree<string, Tree<int, string> >.full (mainTreeCompareDataFunction, free,
        (data) => {
          var tree = (Tree<string, Tree<int, string>>) data;
          // Ownership is transfered to this local var which calls unref when it goes out of scope
          var tree2 = (owned) tree;
        });
    // Random sized for loop
    for (int i = 0; i < int_range (1000, 10001); i++) {
        // If a condition is met (i is even)
        if (i % 2 == 0) {
            // Create a Tree to nest onto mainTree
            Tree<int, string> treeToNest = new Tree<int, string>.full (treeToNestCompareDataFunction, null, free);
            // Insert random content into treeToNest
            treeToNest.insert (int_range (0, 101), randomString ());
            // Insert the tree onto mainTree
            mainTree.insert (randomString (), treeToNest);
        }
    }

    // Empty the tree
    mainTree.@foreach ((mainTreeKey, mainTreeValue) => {
        mainTree.remove (mainTreeKey);
        return false;
    });

    return 0;
}

public string randomString () {
    string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    string stringToReturn = "";
    // Create a random 8 character string
    for (int i = 0; i < 8; i++) {
        stringToReturn += charset[int_range (0, charset.length)].to_string ();
    }
    return stringToReturn;
}

public int treeToNestCompareDataFunction (int a, int b) {
    if (a < b) return -1;
    if (a > b) return 1;
    return 0; 
}

public int mainTreeCompareDataFunction (string a, string b) {
    return strcmp (a, b);
}