8

10 个内存引发的大坑,你能躲开几个?(1)

 4 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI0MjEwMDMzNQ%3D%3D&%3Bmid=2652517958&%3Bidx=1&%3Bsn=374118e8dcd5bf7853575ba0c62f0c54
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

对程序员来说内存相关的 bug 排查难度几乎和多线程问题并驾齐驱, 当程序出现运行异常时可能距离真正有 bug 的那行代码已经很远了 ,这就导致问题定位排查非常困难,这篇文章将总结涉及内存的一些经典 bug ,快来看看你知道几个,或者你的程序中现在有几个。。。

返回局部变量地址

我们来看这样一段代码:

int fun() {  
int a = 2;
return &a;
}
void main() {
int* p = fun();
*p = 20;
}

这段代码非常简单,func 函数返回一个指向局部变量的地址,main 函数中调用 fun 函数,获取到指针后将其设置为 20。

你能看出这段代码有什么问题吗?

问题在于局部变量 a 位于 func 的栈帧中,当 func 执行结束,其栈帧也不复存在,因此 main 函数中调用 func 函数后得到的指针 指向一个不存在的变量

emq2qe3.png!mobile

尽管上述代码仍然可以“正常”运行,但如果后续调用其它函数比如funcB,那么指针p指向的内容将被 funcB 函数的栈帧内容覆盖掉,又或者修改指针 p 实际上是在破坏 funcB 函数的栈帧,这将导致极其难以排查的 bug。

错误的理解指针运算

int sum(int* arr, int len) {
  int sum = 0;
  for (int i = 0; i 
	

这段代码本意是想计算给定数组的和,但上述代码并没有理解指针运算的本意。

指针运算中的加1并不是说移动一个字节而是移动一个单位, 指针指向的数据结构大小就是一个单位 。因此,如果指针指向的数据类型是 int,那么指针加 1 则移动 4 个字节(32位),如果指针指向的是结构体,该结构体的大小为 1024 字节,那么指针加 1 其实是移动 1024 字节。

zQ7RR3f.png!mobile

从这里我们可以看出, 移动指针时我们根本不需要关心指针指向的数据类型的大小 ,因此上述代码简单的将arr += sizeof(int)改为arr++即可。

解引用有问题的指针

C语言初学者常会犯一个经典错误,那就是从标准输入中获取键盘数据,代码是这样写的:

int a;

scanf ( "%d" , a);

很多同学并不知道这样写会有什么问题,因为上述代码有时并不会出现运行时错误。

原来 scanf 会将a的值当做地址来对待,并将从标准输入中获取到的数据写到该地址中。

这时接下来程序的表现就取决于a的值了,而上述代码中局部变量a的值是不确定的,那么这时:

  1. 如果a的值作为指针指向代码区或者其它不可写区域,操作系统将立刻kill掉该进程,这是最好的情况,这时发现问题还不算很难

  2. 如果a的值作为指针指向栈区,那么此时恭喜你,其它函数的栈帧已经被破坏掉了,那么程序接下来的行为将脱离掌控,这样的 bug 极难定位

  3. 如果a的值作为指针指向堆区,那么此时也恭喜你,代码中动态分配的内存已经被你破坏掉了,那么程序接下来的行为同样脱离掌控,这样的bug也极难定位

Zr6BbqI.png!mobile

- - - - - - - - - - 线 - - - - - - - - - - -

P H P ( p h p f a m i l y )   P H P e r

稿 稿

稿

s h e n z h e 1 6 3 @ g m a i l . c o m

  码农的荒岛求生        

qM7RBj.jpg!mobile

aamqE3z.jpg!mobile 素质三连biubiubiu~ yUfmAfJ.png!mobile


Recommend

  • 44
    • www.10tiao.com 6 years ago
    • Cache

    文件操作中的几个大坑

    点击上方“程序员大咖”,选择“置顶公众号” 关键时刻,第一时间送达! ...

  • 13

    遇到一个诡异的问题,在固定的 VPC 环境里运行了一年的 ECS 机器,突然连不上 RDS 数据库,而这个问题在早些时候,也曾在另外一台机器上出现过。 为了避免后续在业务日常运行和重大活动过程中出现类似问题,我们和阿里云进行了反馈...

  • 14

    对程序员来说内存相关的 bug 排查难度几乎和多线程问题并驾齐驱,当程序出现运行异常时可能距离真正有 bug 的那行代码已经很远了,这就导致问题定...

  • 10
    • blog.securemymind.com 4 years ago
    • Cache

    小心躲开“免费”的企业版安全软件

    小心躲开“免费”的企业版安全软件 – 安全意识博客Skip to content 惊闻360免费企业版已经有20...

  • 5

    “内卷化”这个大坑,希望你能避开 15天0基础极速入门数据分析,掌握一套数据分析流程和方法,学完就能写一份数据报告!了解一下>>...

  • 3
    • www.niaogebiji.com 3 years ago
    • Cache

    定位理论5大坑,你踩过几个?

    定位理论5大坑,你踩过几个?_广告营销策略_鸟哥笔记 定位理论5大坑,你踩过几个? 品牌圈圈...

  • 10
    • www.sino-manager.com 3 years ago
    • Cache

    躲开高股息陷阱

    躲开高股息陷阱 在年报季,如何选择慷慨分红的公司成了投资者比较关心的话题之一。高股息虽然是“真金白银”分给投资者,但其中的陷阱也不少。笔者建议,投资者需...

  • 4

    融资避坑指南丨BP撰写的十大坑,你踩过几个?开氪精选·2022-08-23 02:34一份好的BP是融资的敲门砖。 商业计划书也被我...

  • 3
    • news.iresearch.cn 2 years ago
    • Cache

    没躲开“天坑专业“的年轻人

    没躲开“天坑专业“的年轻人 ...

  • 8

    人过了一定岁数就开始焦虑,这被称作是“中年危机”,害怕落后跟不上时代被后浪拍死,人如此,品牌亦是。每一个品牌的成长过程,都伴随着一个时间段的人,他们了解你,认同你,但对新生的消费群来说,他们并不清楚你是谁。于是你可以想象,当品牌成长到一个相貌...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK