前言:
计算机其实很笨,但它却总能欺骗自以为很聪明的人类;如果它的愚笨被聪明的人利用,你能想象会发生什么吗?
1.递归实现二叉树正常情况:
二叉树数据结构及算法声明
//
// T-Tree.hpp
// T-Tree
//
// Created by 韩立国 on 2021/10/29.
//
#ifndef T_Tree_hpp
#define T_Tree_hpp
#include <stdio.h>
struct T_struct
{
float Date;
T_struct *Left_T;
T_struct *Right_T;
int n;
};
extern void Create_T_Tree(T_struct * &T_struct_Root,unsigned int m);
extern void Front_Search(T_struct *T_struct_Root);
extern void Back_Search(T_struct *T_struct_Root);
extern void Midll_Search(T_struct *T_struct_Root);
//extern bool Insert(int *Root_Node,int Who,int Where);
//extern bool Delete(int *Root_Node,int Who,int Where);
#endif /* T_Tree_hpp */
二叉树算法实现
//
// T-Tree.cpp
// T-Tree
//
// Created by 韩立国 on 2021/10/29.
//
#include "T-Tree.hpp"
#include <stdlib.h>
#include <iostream>
//#include <malloc.h>
using namespace std;
//T_struct *T_struct_Root;
//T_struct *Root_Node=&T_struct_Root;
/*
建立二叉树
*/
unsigned int m;
void Create_T_Tree(T_struct* &T_struct_Root,unsigned int m)
{
std::cout<<"I WILL CREATE A TREE,ARE U READY?\n";
std::cout<<"please put in a VALue :"<<m<<"LEVEL\n";
if(m<3)
{
//while(m>0)
//{
m++;
//T_struct_Root=(T_struct*)malloc(sizeof(T_struct));
T_struct_Root=new T_struct;
cin>>T_struct_Root->Date;
T_struct_Root->Left_T=NULL;
T_struct_Root->Right_T=NULL;
T_struct_Root->n=m;
Create_T_Tree(T_struct_Root->Left_T,m);
Create_T_Tree(T_struct_Root->Right_T,m);
//}
m--;
}
else
{
cout<<"OK!\n";
//T_struct_Root=NULL;
//return; //T_struct_Root->Date;
}
}
/*
中序遍历搜索
*/
void Front_Search(T_struct * T_struct_Root)
{
if(T_struct_Root==NULL/*||T_struct_Root->Left_T==NULL||T_struct_Root->Right_T==NULL*/)
{
cout<<"BOttom is\n";
//return;
}else
{
Front_Search(T_struct_Root->Left_T);
cout<<"Date is :"<<T_struct_Root->Date<<" I aM Level : "<<T_struct_Root->n<<"\n";
Front_Search(T_struct_Root->Right_T);
}
}
测试用例
//
// main.cpp
// T-Tree
//
// Created by 韩立国 on 2021/10/29.
//
#include <iostream>
#include "T-Tree.hpp"
//#include <stdlib.h>
//#include <malloc.h>
using namespace std;
T_struct *T_struct_Root={0};
int main(int argc, const char * argv[]) {
Create_T_Tree(T_struct_Root,0);
std::cout << "T_struct_Root is :"<<T_struct_Root<<"\n";
Front_Search(T_struct_Root);
//std::cout << "Hello, World!\n";
return 0;
}
测试结果:
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :0LEVEL
1
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :1LEVEL
2
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
3
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
4
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :1LEVEL
5
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
6
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
7
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
T_struct_Root is :0x1007063d0
BOttom is
Date is :3 I aM Level : 3
BOttom is
Date is :2 I aM Level : 2
BOttom is
Date is :4 I aM Level : 3
BOttom is
Date is :1 I aM Level : 1
BOttom is
Date is :6 I aM Level : 3
BOttom is
Date is :5 I aM Level : 2
BOttom is
Date is :7 I aM Level : 3
BOttom is
Program ended with exit code: 0
2.对二叉树内部变量不初始化,引发访问异常
32 T_struct_Root=new T_struct;
33 cin>>T_struct_Root->Date;
34 //T_struct_Root->Left_T=NULL; //指针无初始化
35 //T_struct_Root->Right_T=NULL; //指针无初始化
测试结果
T_struct_Root is :0x10071fd20
BOttom is
Date is :3 I aM Level : 3
(lldb)
在访问第3层,Date 3之后发生异常退出。
看下栈数据:
T_struct_Root T_struct * 0x10071fd20 0x000000010071fd20
Date float 1
Left_T T_struct * 0x10113cde0 0x000000010113cde0
Date float 2
Left_T T_struct * 0x10071fd40 0x000000010071fd40
Date float 3
Left_T T_struct * NULL 0x0000000000000000
Right_T T_struct * 0x7ff8058b0012 0x00007ff8058b0012 //异常地址
n int 3
Right_T T_struct * 0x10113ce00 0x000000010113ce00
n int 2
Right_T T_struct * 0x101006420 0x0000000101006420
Date float 5
Left_T T_struct * 0x101008190 0x0000000101008190
Right_T T_struct * 0x101236210 0x0000000101236210
Date float 7
Left_T T_struct * NULL 0x0000000000000000
Right_T T_struct * 0x10 0x0000000000000010
n int 3
n int 2
n int 1
此时T_struct_Root->Right_T指向了违法地址,引发异常,所以Front_Search( )退出了。
Right_T T_struct * 0x7ff8058b0012 0x00007ff8058b0012
Date float 2.59967951E+28
Left_T T_struct * 0x6e9c0017a00fffee
Right_T T_struct * 0xa022ffee27890023
n int 1854930967
n int 3
那么这块数据是怎么来的呢?
为了更好的跟踪Create_T_Tree(T_struct_Root,0)函数的执行,对源代码稍作调整
unsigned int m;
void Create_T_Tree(T_struct* &T_struct_Root,unsigned int m)
{
std::cout<<"I WILL CREATE A TREE,ARE U READY?\n";
std::cout<<"please put in a VALue :"<<m<<"LEVEL\n";
if(m<3)
{
//while(m>0)
//{
m++;
T_struct_Root=(T_struct*)malloc(sizeof(T_struct));
//T_struct_Root=new T_struct;
cin>>T_struct_Root->Date;
//T_struct_Root->Left_T=NULL; //指针无初始化
//T_struct_Root->Right_T=NULL; //指针无初始化
cout<<"T_struct_Root->Left_T is:"<<T_struct_Root->Left_T<<"\n";
cout<<"T_struct_Root->Right_T is:"<<T_struct_Root->Right_T<<"\n";
T_struct_Root->n=m;
Create_T_Tree(T_struct_Root->Left_T,m);
Create_T_Tree(T_struct_Root->Right_T,m);
//}
m--;
}
else
{
cout<<"OK!\n";
//T_struct_Root=NULL;
//return; //T_struct_Root->Date;
}
}
让每一次Create_T_Tree(T_struct* &T_struct_Root,unsigned int m)都输出内存块被放Date后T_struct_Root->Left_T、T_struct_Root->Right_T究竟有什么,执行后会看到,奇妙的事情被发现了:
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :0LEVEL
1
T_struct_Root->Left_T is:0x10
T_struct_Root->Right_T is:0x0
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :1LEVEL
2
T_struct_Root->Left_T is:0xa000000010070002
T_struct_Root->Right_T is:0x4000000010070536
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
3
T_struct_Root->Left_T is:0x0
T_struct_Root->Right_T is:0x7ff8058b162d
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
4
T_struct_Root->Left_T is:0x7ff90671000a
T_struct_Root->Right_T is:0x0
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :1LEVEL
5
T_struct_Root->Left_T is:0x7ff906710008
T_struct_Root->Right_T is:0x0
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
6
T_struct_Root->Left_T is:0xe
T_struct_Root->Right_T is:0x0
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :2LEVEL
7
T_struct_Root->Left_T is:0x0
T_struct_Root->Right_T is:0x0
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
I WILL CREATE A TREE,ARE U READY?
please put in a VALue :3LEVEL
OK!
T_struct_Root is :0x10112f940
BOttom is
Date is :3 I aM Level : 3
在Date=2被放置后,T_struct_Root->Left_T is:0xa000000010070002、T_struct_Root->Right_T is:0x4000000010070536,可见这个指针数据是原先堆内存被使用后残留的数据,而又没有初始化对其归零,所以导致残留数据被用作指针,原本没有数据的指针指向了未知区域;而这个指针是在下一步递归中使用到的,被用作参数压栈,并被用作变量被写入下一次申请内存的地址,从而导致程序失控。这会导致严重的堆内存写入错误,如果存在函数对其读数据,则会造成非法地址访问;Front_Search(T_struct * T_struct_Root)抛出异常就是这样导致的。