本文目的是为了更好的理解指针和内存管理

背景

我们定义一个变量A,修改另外一个一个变量B,导致A的值被修改,我们称它为内存污染。

案例

如下程序,正常的预期输出应该是:97 98 256 ,但正确的结果却是1 0 256 ,意不意外,惊不惊喜

这时候主要问题发生在int *ptr = (int *)&b; 这里,对&b 强类型转换,污染了a 的内存

a 的地址比b 地址大(堆从低到高, 栈从高到低分配地址 )

————————————

#include <stdio.h>

int main(void)

{

    char a = 'a', b = 'b';

    int *ptr = (int *)&b;

    *ptr = 256;

    printf("%d,%d,%d \n", a, b, *ptr); // 1 0 256

    return 0;

}

 

验证

我们通过gdb调试,打印出各个变量的地址

————————————

$ gdb a.out

(gdb) b 7

Breakpoint 1 at 0x100000f47: file test.c, line 7.

(gdb) b 11

Breakpoint 2 at 0x100000f77: file test.c, line 11.

Thread 2 hit Breakpoint 1, main () at test.c:7

7          int *ptr = (int *)&b;

(gdb) x/1tb &a

0x7ffeefbff55b: 01100001

(gdb) x/1tb &b

0x7ffeefbff55a: 01100010

(gdb) n

8          *ptr = 256;

(gdb) n

10          printf("%d,%d,%d \n", a, b, *ptr); // 1 0 256

(gdb) n

1,0,256

Thread 2 hit Breakpoint 2, main () at test.c:11

11          return 0;

(gdb) x/1tb &a

0x7ffeefbff55b: 00000001

(gdb) x/1tb &b

0x7ffeefbff55a: 00000000

(gdb) x/4tb ptr

0x7ffeefbff55a: 00000000        00000001        00000000        00000000

————————————

我们在*ptr = 256; 这里打了断点,然后分别看执行前后a ,b 的变化

我们先在断点前,使用gdb命令x/1tb &a 查看内存

✪ a 的地址0x7ffeefbff55b 值为十进制97

✪ b 的地址0x7ffeefbff55a 值为十进制98

 

结论:a 的地址比b 的地址高

(gdb) x/1tb &a

0x7ffeefbff55b: 01100001

(gdb) x/1tb &b

0x7ffeefbff55a: 01100010

————————————

然后我们执行*ptr = 256; 这句后,再次查看:

(gdb) x/1tb &a

0x7ffeefbff55b: 00000001

(gdb) x/1tb &b

0x7ffeefbff55a: 00000000

(gdb) x/4tb ptr

0x7ffeefbff55a: 00000000        00000001        00000000        00000000

————————————

ptr赋值245后,内存中值为:00000000 00000001 00000000 00000000

直接污染了a 的内存,把a 值修改为了00000001 因为ptr为int* 类型,占用4个字节,a 的地址比ptr 高1,属于4个字节之内,所以被污染了。

是不是很神奇呢,下次遇到这种坑小伙伴一定要注意哦!

————————————

看到这里你是不是对C语言又有了一点新的认知呢~

如果你喜欢这篇文章的话,动动小指,点个赞再走~

如果你想学编程,小编推荐一个C语言/C++编程学习基地【点击进入】!

 

一个活跃、高逼格、高层次的编程学习殿堂;编程入门只是顺带,思维的提高才有价值!

涉及:编程入门、游戏编程、网络编程、Windows编程、Linux编程、Qt界面开发、黑客等等....

C语言的污垢,一个能污染内存的神秘操作!神级坑位再现~的更多相关文章

  1. C语言学习(记录)【内存相关_1:内存基础】

    本学习是基于嵌入式的C语言学习记录(课程内容来源于某位老师的网络课程,为了证明不是在打广告,就不写出老师的名字了,感谢.) -------------------------------------- ...

  2. Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器

    Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...

  3. 从硬件到语言,详解C++的内存对齐(memory alignment)

    转载请保留以下声明 作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则 ...

  4. 从硬件到语言,详解C++的内存对齐(memory alignment)(一)

    作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则,但不一定对他有很深 ...

  5. Swift3.0语言教程获得一个公共的前缀

    Swift3.0语言教程获得一个公共的前缀 Swift3.0语言教程获得一个公共的前缀,当在一个程序中有多个字符串时,我们需要判断是否有两个字符串有公共的前缀时,是很困难的.在NSString中的co ...

  6. 采用 PAT工具及CSP语言,对一个问题进行自动机 建模

    pat是新加坡国立开发的工具,需要的去官网下http://www.comp.nus.edu.sg/~pat/ ,学了一天,是个不错的自动机验证工具,感觉还不错啊. 验证一个数是否为斐波那契数且为质数 ...

  7. 李洪强iOS开发之【零基础学习iOS开发】【02-C语言】02-第一个C语言程序

    前言 前面已经唠叨了这么多理论知识,从这讲开始,就要通过接触代码来学习C语言的语法.学习任何一门语言,首先要掌握的肯定是语法.学习C语言语法的目的:就是能够利用C语言编写程序,然后运行程序跟硬件(计算 ...

  8. 不好意思啊,我上周到今天不到10天时间,用纯C语言写了一个小站!想拍砖的就赶紧拿出来拍啊

    花10天时间用C语言做了个小站 http://tieba.yunxunmi.com/index.html 简称: 云贴吧 不好意思啊,我上周到今天不到10天时间,用纯C语言写了一个小站!想拍砖的就赶紧 ...

  9. 用Racket语言写了一个万花筒的程序

    用Racket语言写了一个万花筒的程序 来源:https://blog.csdn.net/chinazhangyong/article/details/79362394 https://github. ...

随机推荐

  1. jenkins 下载插件失败 有效的处理办法(亲测)

    jenkins 下载插件失败,提示: java.io.IOException: Downloaded file /app/jenkins_home/plugins/jacoco.jpi.tmp doe ...

  2. [LeetCode]621. 任务调度器(贪心)

    题目 给定一个用字符数组表示的 CPU 需要执行的任务列表.其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务.任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完.CP ...

  3. php判断请求方式

    1 /** 2 * 判断是否为get请求 3 * 4 * @return bool 5 */ 6 function is_get():bool 7 { 8 return $_SERVER['REQUE ...

  4. 立下flag!

    从今日(2020年6月29日)开始,直到两个月的暑假结束2020年8月31日,每天vp一场div3,至少要ac4道题目.

  5. React使用AntV G6实现流程图

    安装 npm install @antv/g6 --save 引用 import G6 from '@antv/g6' 自定义节点 /** * 方式一 */ G6.registerNode('rect ...

  6. Layer层自定义

    keras允许自定义Layer层, 大大方便了一些复杂操作的实现. 也方便了一些novel结构的复用, 提高搭建模型的效率. 实现方法 通过继承keras.engine.Layer类, 重写其中的部分 ...

  7. GitBook 3.2.3入门

    简介 GitBook 是一个基于 Node.js 的命令行工具,可使用 GitHub / Git.Markdown.AsciiDoc来制作精美的电子书.GitBook 可以将文档作为静态网站或电子书( ...

  8. Spring Cloud系列(三):Eureka源码解析之服务端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-starter-netflix-eureka-ser ...

  9. 制作u盘启动盘

    制作u盘启动盘 如果是想要制作 windows 系统启动盘,windows 官网提供途径,这里不在赘述. 以下讨论制作 centos 系统启动盘,需要 centos 系统文件,开源,可从官网下载得到. ...

  10. Java知识系统回顾整理01基础02面向对象03方法

    一.根据实例给出"方法"的定义 在LOL中,一个英雄可以做很多事情,比如超神,超鬼,坑队友 能做什么在类里面就叫做方法 比如队友残血正在逃跑,你过去把路给别人挡住了,导致他被杀掉. ...