zoukankan      html  css  js  c++  java
  • 对失控指针引起的错误过程的准确观察

    // Listing 8.9 - Demonstrates a stray pointer
      
    typedef unsigned short int USHORT;
    #include <iostream>
      
    int main()
    {
       USHORT * pInt = new USHORT; // 声明第一个指针,分配了一块内存块(指针自身占用另一块内存块)
       *pInt = 10; // 使用指针并赋值,正确。short类型会把内存的值改成0A00,是2个字节,而不是4个字节。
       std::cout << "*pInt: " << *pInt << std::endl;
       delete pInt;  // 删除指针,正确。告诉编译器将使用该内存区域保存其它东西。
                     // 让编译器释放内存,但指针本身存在。它现在就是一个失控指针(野指针)。应该把它改成空指针 pInt=NULL;
                     // 如果删除一个指针之后,又对它删除了一次,那么程序就是不确定的。任何情况都有可能发生。只有幸运的话,程序也许会崩溃。
                     // 如果删除一个空指针,什么事情也不会发生,这样非常安全。
      
       long * pLong = new long; // 声明第二个指针,分配了一块内存块(指针自身占用另一块内存块)
                                // 但是第一个指针的内存块被清除以后,第二个指针就可以使用那块内存块了(事实也是如此)
       *pLong = 90000; // 使用指针并赋值,正确。90000 = 00 01 5F 90,实际存储为 90 5F 01 00 (小端存储,按Byte的倒序排列)
       std::cout << "*pLong: " << *pLong << std::endl;
      
       *pInt = 20;      // 使用指针并赋值,错误。因为这个指针已经被删除。20 = 00 14,内存里存储为14 00
                        // 如果对空指针赋值,程序将崩溃,这是与失控指针相比,空指针的另一个优点
      
       std::cout << "*pInt: " << *pInt  << std::endl; // 使用指针,错误,尽管打印了第一个指针期望的正确值,但其实错误,因为它已经被删除了
       std::cout << "*pLong: " << *pLong  << std::endl; // 使用指针,错误,打印结果不是第二个指针期望的值,尽管它存在内存里,但内容已被改写
       delete pLong; // 删除指针,正确。
       return 0;
    }

    输出结果:
    *pInt: 10 // 简单
    *pLong: 90000 // 简单
    *pInt: 20 // 输出结果正确,但其实鸠占鹊巢使用内存,以后不保证正确,而且影响了应该正确输出的另一个变量。
    *pLong: 65556 // 输出结果错误,不是期望的值,原因是失控指针pInt与正常指针pLong使用同一块内存,于是其内存的一部分数据被改写,即90 5F 00 01的低端部分被改写,改成:14 00 01 00,再变回人类正常数字的顺序,即00 01 00 14 = 65556

    疑问1:《21天学通C++》中文版书上p157说 90000(00 01 5F 90)实际存储为5F 90 00 01 ,即按照Word长度反序排列,这应该是错误。整个过程使用VC++观察内存值,特别清楚

    --------------------------------------
    继续1,如果把第一个指针的声明语句改成:
    long * pInt = new long;
    那么打印结果是:
    *pInt: 10
    *pLong: 90000
    *pInt: 20
    *pLong: 20 (第二个指针指向的内容与第一个指针指向的内容长度完全一致)

    --------------------------------------
    继续2,如果把第一个指针的声明语句改成:
    char * pInt = new char;
    那么
    *pInt = 10; // 只把一个字节改成 0A
    使用失控指针的时候:
    *pInt = 20; // 只把一个字节改成 14
    最终第二个指针的值变成 00 01 5F 14 = 89876

    --------------------------------------
    继续3:有空可以看看这个程序的反汇编,研究一下。


    参考,关于大端小端的图,很形象:
    http://www.cppblog.com/tx7do/archive/2009/01/06/71276.html

  • 相关阅读:
    CSS
    CSS
    CSS
    CSS
    CSS
    CSS
    FLASK
    人物
    关于反射
    释放c盘空间
  • 原文地址:https://www.cnblogs.com/findumars/p/3698013.html
Copyright © 2011-2022 走看看