对失控指针引起的错误过程的准确观察


// 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

对失控指针引起的错误过程的准确观察,码迷,mamicode.com

时间: 2024-10-03 13:14:33

对失控指针引起的错误过程的准确观察的相关文章

结构体指针之 段错误 具体解释(segmentation fault)

一个网友问了我一个问题.一个C程序执行出现了段错误,这个问题非常好.非常多刚開始学习的人都easy犯这个错误,详细代码例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 这个编译没有问题,可是执行是段错误    Segmentation fault 由于你定义了一个结构体指针p.用来指向此类

纪念在“返回局部变量的指针”导致的错误上耗费的一天

最近在写编译器,有这样一段代码 1 typedef struct{ 2 int symbolnum; 3 char *name; //id36 4 int i; //int37 5 float f; //float38 6 char *s; //string39 7 }To; 8 typedef To* Token; 1 Token ReadToken() //从fp文件中读取一行形如(36,sum)的行,返回值被压栈 2 { 3 char strLine[1024]; 4 char n1[10

C语言指针的常见错误

main(){ //不能使用不同类型的给指针赋值 /* int a = 5; double* p = &a; printf("%d",*p); */ //野指针不可以使用, // int* p ; //printf("%d",*p); system("pause"); }

C++ 中判断非空的错误指针

最近在写网络上的东西,程序经过长时间的运行,会出现崩溃的问题,经过DUMP文件的查看,发现在recv的地方接收返回值的时候,数据的长度异常的大差不多16亿多字节.而查看分配后的char指针显示为错误的指针,这可能是接收数据不对应产生的问题解决思路如下: 1.对返回值长度进行判断,如果超过项目内最大的返回值就直接return(比如我项目内的最大返回值为5000,哪么我设定的值为10000); 2.对char指针进行判断,由于这里返回的数据是有的,只是解析不出来而已,这里就是一个非空的错误指针,所以

内核中判断返回指针是否错误方法

内核中判断返回指针是否错误的方法:使用IS_ERR或者IS_ERR_OR_NULL. 参考include/linux/err.h #define MAX_ERRNO  4095 #ifndef __ASSEMBLY__ #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) static inline void * __must_check ERR_PTR(long error) { return (void *) e

野指针错误实例

野指针,也就是指向不可用内存区域的指针.通常对这种指针进行操作的话,将会使程序发生不可预知的错误. 这是野指针的定义,但很多C语言新手对它还是很陌生,下面我就简单举一个例子来看一看.在VC6.0中输入以下代码: #include <malloc.h> #include <stdio.h> void main() { char *p; //...可能有别的很多操作 if(p != NULL) { free(p); } else { p = (char *)malloc(4); } /

C和指针 第十五章 错误报告perror和exit

15.1 错误报告 perror 任何一种程序都存在出错的可能,包括系统的函数库,当出现错误时,系统提示发生错误,标准库函数在一个外部整型变量中保存错误代码,然后把错误代码传给用户程序,提示错误原因.perror简化了向用户报告特定错误过程. void perror(char const * message); perror,接受字符串,先打印出这个字符串,然后在后面跟一个分号空格,然后打印出解释errno的错误代码的信息 #include <stdio.h> #include <err

anaconda命令行运行过程中出现的错误

在anaconda中使用jupyter时,出现各种bug,大多数是和tornado相关的问题,遇到这一问题一般是版本不匹配的原因,所以要对jupyter和tornado进行相应的版本匹配.如果使用anaconda过程中出现其他的属性错误等,要观察出现的错误所属包,然后尝试卸载当前包,重新安装新的版本的匹配包.一定要好好分析错误原因. 原文地址:https://www.cnblogs.com/jianglinliu/p/10493847.html

使用devpartner的blockchecker检查c++内存错误

在仿写stl的过程中,被一处内存错误卡了很久.当内存池需要多次malloc时会出现堆损坏的错误,初步判断是数组越界,但总是检查不出来.一开始用Dr.Memory检查不出来,就试了一下devpartner.官网链接 http://www.borland.com/zh-CN/Products/Software-Testing/Automated-Testing/Devpartner-Studio devpartner安装完后会自动在vs上装插件,但是那个插件好像没什么用.我是直接在安装目录下找到bl