Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;避免检查双指针持有的未初始化值_C++_Pointers_Initialization_Valgrind_Double Pointer - Fatal编程技术网

C++ C++;避免检查双指针持有的未初始化值

C++ C++;避免检查双指针持有的未初始化值,c++,pointers,initialization,valgrind,double-pointer,C++,Pointers,Initialization,Valgrind,Double Pointer,解决 问题最终源于数据结构的设计。要删除根元素,必须有一个堆分配的(新的)指针指向它,这在原始情况下是不可能的,因为数据直接由树保存。现在有一个节点结构保存所有数据,树类包含所有方法和根指针 我有一个双指针target\u address初始化为NULL,我以后必须检查*target\u address是否为NULL。在这两者之间,函数保证*target_address指向未初始化的值,但Valgrind一直抱怨我只有在删除根元素时才读取未初始化的值 树_delete也抱怨未初始化值;我敢肯

解决

问题最终源于数据结构的设计。要删除根元素,必须有一个堆分配的(新的)指针指向它,这在原始情况下是不可能的,因为数据直接由树保存。现在有一个
节点
结构保存所有数据,树类包含所有方法和根指针


我有一个双指针
target\u address
初始化为
NULL
,我以后必须检查
*target\u address
是否为NULL。在这两者之间,函数保证
*target_address
指向未初始化的值,但Valgrind一直抱怨我只有在删除根元素时才读取未初始化的值

树_delete也抱怨未初始化值;我敢肯定它也在抱怨*目标地址

void tree<T>::tree_delete(tree<T>** target_address) {
    tree<T>* target = *target_address;
    // first case: no left subtree, replace with right subtree (or NULL for a leaf) 
    if (!target->left) 
        *target_address = target->right;

    // second case: no right subtree, replace with left subtree
    else if (!target->right) 
        *target_address = target->left;

    // third case: both subtrees, find second largest by taking rightmost left tree
    else {
        tree<T>** second_largest_address = &target->left;  // start at target's left tree
        while ((*second_largest_address)->right)  // keep going right
            second_largest_address = &((*second_largest_address)->right);  
        // reached the rightmost left
        tree<T>* second_largest = *second_largest_address;
        *target_address = second_largest;  // delete target by replacing it with second largest
        // second largest guranteed to not have a right subtree, so can treat as case 2 by shifting
        *second_largest_address = second_largest->left;  
        second_largest->left = target->left;
        second_largest->right = target->right;
    }
    delete target;
}
类似于的代码,如果(!this)返回空非常可疑。这是一个无操作,并指示其他地方未定义的行为。难怪Valgrind报告您的代码出现问题

更糟糕的是,请查看
树中的代码\u find

tree<T>* root = this;   // <-- ensures *target_address points to stack variable !
tree<T>** target_address = &root; // Set out pointer to stack variable

tree*root=this;//能否显示
tree::data
的定义?
tree\u find
如果数据与第一个节点匹配,则返回指向堆栈变量的指针
tree*root
是堆栈变量,
tree**target\u address=&root
-堆栈变量的地址,
*target\u address\u handle=target\u address-将不存在的变量的地址发送回调用方。我不太清楚为什么要返回指向所需节点的指针的地址,而不仅仅是指向所需节点的指针!树数据只是
T数据
,其他属性是
Tree*left,*right
typeid(T)==typeid(T)
那么总是正确的@MattMcNabb啊对,这证实了我的怀疑。。。想想看,我不认为我需要三个指针;我会尝试摆脱它,看看它是否仍然有效,是的,typeid(T)=typeid(T)。。。忘记C++是强类型的,可能有人可以尝试在不同类型的树上搜索
void tree<T>::tree_delete(tree<T>** target_address) {
    tree<T>* target = *target_address;
    // first case: no left subtree, replace with right subtree (or NULL for a leaf) 
    if (!target->left) 
        *target_address = target->right;

    // second case: no right subtree, replace with left subtree
    else if (!target->right) 
        *target_address = target->left;

    // third case: both subtrees, find second largest by taking rightmost left tree
    else {
        tree<T>** second_largest_address = &target->left;  // start at target's left tree
        while ((*second_largest_address)->right)  // keep going right
            second_largest_address = &((*second_largest_address)->right);  
        // reached the rightmost left
        tree<T>* second_largest = *second_largest_address;
        *target_address = second_largest;  // delete target by replacing it with second largest
        // second largest guranteed to not have a right subtree, so can treat as case 2 by shifting
        *second_largest_address = second_largest->left;  
        second_largest->left = target->left;
        second_largest->right = target->right;
    }
    delete target;
}
==25887== Conditional jump or move depends on uninitialised value(s)
==25887==    at 0x401764: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x4013AA: main (in /home/johnson/Code/tree/treetest)
==25887==  Uninitialised value was created by a stack allocation
==25887==    at 0x40175A: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887== 
After reading *target tree address
Before read
==25887== Use of uninitialised value of size 8
==25887==    at 0x401A75: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x40178E: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x4013AA: main (in /home/johnson/Code/tree/treetest)
==25887==  Uninitialised value was created by a stack allocation
==25887==    at 0x401A46: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887== 
==25887== Use of uninitialised value of size 8
==25887==    at 0x401AA5: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x40178E: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x4013AA: main (in /home/johnson/Code/tree/treetest)
==25887==  Uninitialised value was created by a stack allocation
==25887==    at 0x401A46: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887== 
==25887== Use of uninitialised value of size 8
==25887==    at 0x401AF2: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x40178E: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x4013AA: main (in /home/johnson/Code/tree/treetest)
==25887==  Uninitialised value was created by a stack allocation
==25887==    at 0x401A46: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887== 
==25887== Invalid read of size 8
==25887==    at 0x401AF5: tree<int>::tree_delete(tree<int>**) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x40178E: tree<int>::remove(int) (in /home/johnson/Code/tree/treetest)
==25887==    by 0x4013AA: main (in /home/johnson/Code/tree/treetest)
==25887==  Address 0x801f0fc36d is not stack'd, malloc'd or (recently) free'd
tree<T>* root = this;   // <-- ensures *target_address points to stack variable !
tree<T>** target_address = &root; // Set out pointer to stack variable