CC++原始指针之悬空指针、野指针、内存泄露探究

CC++原始指针之悬空指针、野指针、内存泄露探究,第1张

C/C++原始指针之悬空指针、野指针、内存泄露探究
#include 
void update_p_ref(int * intp) {
    int temp = 1;
    intp = &temp;
    printf("up_r_p=%pn", intp);
    printf("up_r_v=%dn", *intp);
    //temp variable "temp" will be collected
}
//transfer parameters as reference
void update_p_ref2(int*& intp_ref) {
    int temp = 3;
    intp_ref = &temp;
    printf("up_rr_p=%pn", intp_ref);
    printf("up_rr_v=%dn", *intp_ref);
}
void update_p_ref3(int& int_ref) {
    int_ref = 5;
    printf("up_rr_p=%pn", &int_ref);
    printf("up_rr_v=%dn", int_ref);
}
void update_p_value(int* intp) {
    *intp = 2;
    printf("up_v_p=%pn", intp);
    printf("up_v_v=%dn", *intp);
}
//transfer parameters as reference
void update_p_value2(int*& intp_ref) {
    *intp_ref = 4;
    printf("up_vr_p=%pn", intp_ref);
    printf("up_vr_v=%dn", *intp_ref);
}
void update_p_value3(int& int_ref) {
    int_ref = 6;
    printf("up_vr_p=%pn", &int_ref);
    printf("up_vr_v=%dn", int_ref);
}

int main() {
    int* p = nullptr; // declare pointer and initialize it
                      // so that it doesn't store a random address
    int i = 0;
    p = &i; // assign pointer to address of object
    int j = *p; // dereference p to retrieve the value at its address
    printf("p=%pn", p);
    printf("p_v=%dn", *p);
    printf("--------transfer parameters pointer as value normally-------n");
    update_p_ref(p);
    printf("p1=%pn", p);
    printf("p1_v=%dn", *p);
    update_p_value(p);
    printf("p2=%pn", p);
    printf("p2_v=%dn", *p);
    printf("--------transfer parameters pointer as reference-------n");
    p = &i;
    update_p_ref2(p);
    printf("p3=%pn", p);
    printf("p3_v=%dn", *p);
    update_p_value2(p);
    printf("p4=%pn", p);
    printf("p4_v=%dn", *p);
    printf("--------above code generate a dangling pointer "p" ,%s%s",
        "because temporary variable "3"(in update_p_ref2) and "5"(in update_p_value2)",
        "'s dynamically allocated memory has been freed with foo stack quitting------- n");
    p = new int(0);
    printf("p_ad=%pn", p);
    printf("p_v_ad=%dn", *p);
    delete(p);//p is a vild pointer now
    printf("p_ad2=%pn", p);
    p = NULL;//or p=nullptr
    printf("p_ad3=%pn", p);
    printf("--------transfer parameters value as reference-------n");
    p = &i;
    update_p_ref3(*p);
    printf("p5=%pn", p);
    printf("p5_v=%dn", *p);
    update_p_value3(*p);
    printf("p6=%pn", p);
    printf("p6_v=%dn", *p);
}

(win10-64位 *** 作系统下运行,分别编译目标平台为win32和x64)输出结果如下,自行体会:

 

 个人总结几个基础点:

①指针指向数据值所在的地址(或者说,当指针的值是地址时,它指向内存中的数据);

②&:寻址符(其后为一个左值——要区别于表达式),对左值寻址获得指针变量,指针变量引用内存地址中的数据;

③*:取值符(其后为一个指针变量),对指针变量取消指针引用,获得指针变量引用的内存地址中的数据;

④对于不是通过关键字new进行内存分配的指针,使用delete释放内存会报错,原因是delete只能释放在堆(heap)中分配的内存空间;其他方式如通过&寻址左值(内存分配在当前作用域的栈中)获取的指针,会在当前堆栈(stack)退出(})时自动释放。

C/C++定义了4个内存区间:代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store)

⑤另外的,造成野指针的几个主要原因:指针变量未初始化;指针释放后之后未置空(p_ad2);指针 *** 作超越变量作用域(p3_v、p4_v)。

⑥悬空指针(p3_v、p4_v,个人认为此处是野指针,待考究)。

———————————————以下来自wiki—————————————

在计算机科学中,指针是一种引用。

原始数据(或仅仅是原始)是可以被读取或写入任何数据的计算机存储器使用一个存储器存取(例如,两者字节和一个是原语)。

数据集合体(或只是聚合)是一组是原语的逻辑在存储器中连续和被作为一个数据集中观察(例如,聚集体可以是3个逻辑上连续的字节,其值表示的3个坐标空间中的点)。当一个聚合完全由相同类型的基元组成时,该聚合可以称为数组;从某种意义上说,多字节原语是一个字节数组,有些程序就是这样使用字的。

在这些定义的上下文中,字节是最小的原语;每个内存地址指定一个不同的字节。数据的起始字节的内存地址被认为是整个数据的内存地址(或基本内存地址)。

存储器指针(或只是指针)是原始的,它的值旨在被用作存储器地址; 据说一个指针指向一个内存地址。也有人说,当指针的值是数据的内存地址时,指针指向数据[在内存中]

更一般地说,指针是一种引用,据说指针引用了存储在内存某处的数据;获得该数据就是取消对指针的引用。将指针与其他类型的引用区分开来的特点是,指针的值被解释为内存地址,这是一个相当低级的概念。

引用作为一个间接级别:指针的值确定在计算中使用哪个内存地址(即哪个数据)。因为间接性是算法的一个基本方面,指针在编程语言中通常表示为一种基本数据类型;在静态(或强)类型编程语言,该类型的指针的判定基准,以该指针指向的类型。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5635236.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存