看看坛友中还有多少是和我一样长年战斗在 C 上的,答对三个就算

2018-09-25 17:36:23 +08:00
 dingzs3

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

void main()

{

    char *p1=(char *)malloc(1024);  //1k

    char *p2=(char *)malloc(4096);  //4k

    memset(p2,0,4096);

    char *p3=(char *)malloc(8192);  //8k

    char *p4=(char *)malloc(128*1024*1024); //128k

    char *p5=(char *)malloc(115*1024);//115k

    printf("p1=%p p2=%p p3=%p p4=%p p5=%p\n",p1,p2,p3,p4,p5);


    memset(p2,'1',20);

    free(p2);

    memset(p2,'y',10);

    printf("p2=%s\n",p2);

    free(p3); //core

    free(p5);

    free(p1);

}

输出: p1=0x1c60010 p2=0x1c60420 p3=0x1c61430 p4=0x7ffbabc2b010 p5=0x1c63440

p2=yyyyyyyyyy?

Segmentation fault (core dumped)

1.p2-p2 为啥不是 1024

2.p4 的地址为啥和其它的不一样

3.为啥在 free(p2)之后还能读写 p2

4.为啥 p2 的打印不是 yyyyyyyyyy1111111111

5.为啥在 free(p3)的时候会 core

8077 次点击
所在节点    程序员
76 条回复
zealot0630
2018-09-26 20:20:28 +08:00
1.p2-p2 为啥不是 1024

glibc 会在 p2 前面用几个字节记录 p2 的分配信息

2.p4 的地址为啥和其它的不一样

p4 用 mmap 分配的,小内存用 brk,大内存用 mmap

3.为啥在 free(p2)之后还能读写 p2

brk 内存分配了就不能释放

4.为啥 p2 的打印不是 yyyyyyyyyy1111111111

p2 还給 glibc 时候,glibc 会吧这段内存返还给链表,p2 这里指向 glibc 内部维护空闲内存的链表

5.为啥在 free(p3)的时候会 core

glibc 维护的空闲内存链表被你破坏了,glibc 就崩了
dingzs3
2018-09-26 22:10:18 +08:00
zmj1316
2018-09-27 07:24:11 +08:00
看 lz 被喷这么惨,帮 lz 说句话,了解这些 ub 的结果不是为了去写这些 ub. ,而是为了在各种不可抗性因素之下,比如笔误 或者🐷队友,导致使用了 ub 而出现 bug 能够尽早发现原因 debug,
假如 崩溃在 free p3 而 free p2 在很前面,起码能考虑到这个可能性,
而写 go 的可能一般不会遇到这种情况,这也是为什么我喜欢 CPP 多于 C,能少很多糟心的事

@zhicheng
@reus
zhicheng
2018-09-27 09:46:03 +08:00
@zmj1316 工作这么多年,头一回听说用 Ub 的行为来 debug,你知道 ub 这是哪两个词的缩写?调试内存问题,你可以用 valgrind 可以用 addresssanitizer,能通过 ub 的行为来定位 bug ?我猜你是神。
zmj1316
2018-09-27 10:07:55 +08:00
@zhicheng 兄弟语文没学好啊...我说的是因为用了 UB 出现 bug,没说用 UB 来 debug 啊......我又不是来抬杠的
zmj1316
2018-09-27 10:12:28 +08:00
@zhicheng 讲的明白一点

`如同法律上写了红灯不要过马路,你非要去讨论什么样的情况下红灯可以过马路,抱歉我理解不了这种行为。`

就是为了明白,路上撞死了个人,不一定是汽车司机故意撞死的,也可能是行人自己闯红灯作死的,划分责任的时候,不要全都怪司机,说不定是行人的责任
dingzs3
2018-09-27 10:20:47 +08:00
@zmj1316 哥们,技术上的问题讨论明白就行了,没必要把问题升华讨论更上层的东西,已经结贴了,本来想删除的,但是不知道怎么删除,而且有十几个人收藏了。技术讨论最好永远局限于技术,也多谢你帮忙解释。
zhicheng
2018-09-27 10:24:12 +08:00
@zmj1316 你说的那不是废话吗?用了 UB 基本上都是要出 Bug 的,大部分 Bug 也是由 UB 引起的,是我语文没学好,还是你逻辑没学好?还是知道 UB 会出现 Bug 是件很牛逼的事?
zmj1316
2018-09-27 10:36:54 +08:00
@dingzs3 抱歉,我的锅,工作不饱和,老老实实搬砖去了,C++写久了 OS 层的东西都快忘光了,感谢 LZ 还让我复习一下 hhhhh
dingzs3
2018-09-27 10:38:15 +08:00
@zmj1316 哈哈哈,以后多交流啊,哥们,C++那套我不怎么熟
bluefalconjun
2018-09-27 13:27:52 +08:00
@dingzs3 如果是为了了解相关知识, 真的应该看书 看 spec 看操作系统 /编译器的实现代码...
在这里写这种 code 来了解... 实话说, 做不到的... 就像你写个黑盒的测试代码 想要来理解里面的实现.. 白盒测试都不一定能完成的事情...
wizardforcel
2018-09-27 14:11:19 +08:00
wizardforcel
2018-09-27 14:14:42 +08:00
@zhicheng 首先 glibc 不是一种实现,而是很多种实现,比如 tmalloc。固定了版本号就固定了实现。

其次,就算你不去利用,黑客也会利用。你觉得被黑是很好玩的事情么??

你以为标准库和编译器都是严格按照标准实现的??你自己搞搞 plt,做做语言律师也就算了,还把这种陋习搬到实际生产中来。你的心真大。呵呵。
wizardforcel
2018-09-27 14:29:39 +08:00
@zhicheng

> 初级工程师总觉得“了解”一点儿别人不知道的很厉害,殊不知这是高级工程师尽量避免的情况。

我认为正好相反,初级工程师只需要知道那个是 UB,高级工程师需要知道具体实现是怎么回事。

虽然大家都知道不能用 UB,但是,知道了产生的后果并且知道为什么不能用,更深刻一些。

知其然而知其所以然,懂??
zhicheng
2018-09-27 15:20:12 +08:00
@wizardforcel 刚好相反,高级工程师根本就不会关心 UB 会产生什么样的行为,因为无论它产生什么样的行为,都是错的,哪怕程序看起来正确。

你知道 UB 会产生什么样的行为能避免被黑?程序能更安全?不,能让程序更安全的是从一开始就尽量避免引入 UB。

没有什么实现是完全正确的,但你明显不能往肯定错误的方向走啊。
aihimmel
2018-09-27 17:03:51 +08:00
@GeruzoniAnsasu 真实堆利用题目

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/492448

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX