百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

你所不知道的C语言:函数调用篇(续)

toyiye 2024-09-08 10:02 3 浏览 0 评论

从递归学习 function call

  • infinite.c
int func() {
    static int count = 0;
    return ++count && func();
}

int main() {
    return func();
}

用 GDB 执行和测试,记得加上 -g:

$ gcc -o infinite infinite.c -g
$ gdb -q infinite
Reading symbols from infinite...done.
(gdb) r
Starting program: /tmp/infinite

Program received signal SIGSEGV, Segmentation fault.
0x00000000004004f8 in func () at infinite.c:3
3                return ++count && func();
(gdb) p count
$1 = 524032

如果将infinite.c 改为以下,重复上述动作:

int func(int x) {
    static int count = 0;
    return ++count && func(x++);
}

int main() {
    return func(0);
}

将得到:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400505 in func (x=1) at infinite.c:3
3                return ++count && func(x++);
(gdb) p count
$1 = 262016

继续修改 infinite.c 為以下,重复上述动作:

int func(int x) {
    static int count = 0;
    int y = x; // local var
    return ++count && func(x++);
}

int main() {
    return func(0);
}

将得到以下:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004004de in func (x=<error reading variable: Cannot access memory at address 0x7fffff7fefec>) at infinite.c:1
1        int func(int x) {
(gdb) p count
$1 = 174677

stack 里面有 x (parameter), y (local variable), return address

  • stack frame

观察UNIX Process 中的 stack 空间:

$ sudo cat /proc/1/maps | grep stack
7fff7e13f000-7fff7e160000 rw-p 00000000 00:00 0 [stack]

60000Hex - 3f000Hex = 21000Hex = 135168Dec
135168 * 4 = 540672
这跟前面的数字很接近!

  • return address 很重要,不管有没有选上,都要有 退路

sp = stack pointer; stack register

(AMD x86_64) A stack frame’s best friends are the two registers rsp and rbp, called the “stack pointer” and the “frame pointer”.

function prologue

function epilogue

(gdb) x /16gx $rsp

5.10. Borrow an

stack-based buffer overflow

  • CVE-2015-7547

vulnerability in glibc’s DNS client-side resolver that is used to translate human-readable domain names, like google.com, into a network IP address. [读者可以网上自行搜索了解]

  • Buffer Overflow : Example of Using GDB to Check Stack Memory(非常好的PPT文档)

准备 gdb-example.c,其內容为

#include <stdio.h>
void foo(char *input) {
    int a1 = 11;
    int a2 = 22;
    char buf[7];
    strcpy(buf, input);
}

void main(int argc, char **argv) {
    foo(argv[1]);
}

编译,记得加上 -g 和 -m32

用 i686 架构执行 GDB:

$ setarch i686 -R gdb -q ./gdb-example
(gdb) break 6
Breakpoint 1 at 0x804847a: file gdb-example.c, line 6.
(gdb) run “whatever”
Starting program: /tmp/gdb-example "whatever"

Breakpoint 1, foo (input=0xffffd406 "whatever") at gdb-example.c:6
6                strcpy(buf, input);

观察 stack 內容:

(gdb) info frame
Stack level 0, frame at 0xffffd180:
eip = 0x8048490 in foo (gdb-example.c:6); saved eip = 0x80484da
called by frame at 0xffffd1b0
source language c.
Arglist at 0xffffd178, args: input=0xffffd40c "whatever"
Locals at 0xffffd178, Previous frame’s sp is 0xffffd180
Saved registers:
ebp at 0xffffd178, eip at 0xffffd17c
(gdb) x &a1
0xffffd15c:        0x0000000b
(gdb) x &a2
0xffffd160:        0x00000016
(gdb) x buf
0xffffd165:        0x44f7f9c0
(gdb) x 0xffffd160
0xffffd160:        0x00000016

藏在 Heap 里细节

free() 释放的是 pointer 指向位于 heap 的连续内存,而非 pointer 本身占有的内存(*ptr)。

举例來说:

#include <stdlib.h>
int main() {
    int *p = (int *) malloc(1024);
    free(p);
    free(p);
    return 0;
}

编译不會有错误,但运行时会失败:

*** Error in './free': double free or corruption (top):
0x000000000067a010 ***

倘若改为以下:

#include <stdlib.h>
int main() {
    int *p = (int *) malloc(1024);
    free(p);
    p = NULL;
    free(p);
    return 0;
}

则会编译和执行都成功。

因此,为了防止对同一个 pointer 作 free() 两次的操作,而导致程序失败,free() 后应该设定为 NULL。

[ 思考] 为什么 glibc 可以侦测出上述程序的 “double free or corruption” 呢?

malloc / free

在 GNU/Linux 里观察 malloc

事先安装 gdb套件

$ sudo apt install gdb gdb-dbg

GDB 操作:

$ gdb -q `which gdb`
Reading symbols from /usr/bin/gdb...
(gdb) start
...
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffe4c8) at ./gdb/gdb.c:25
...
(gdb) p ((double(*)())pow)(2.,3.)
$1 = 8
(gdb) call malloc_stats()
Arena 0:
system bytes     =     135168
in use bytes     =      28000
Total (incl. mmap):
system bytes     =     135168
in use bytes     =      28000
max mmap regions =          0
max mmap bytes   =          0
$2 = -168929728
(gdb) call malloc_info(0, stdout)
<malloc version="1">
<heap nr="0">

glibc 提供了 malloc_stats() 和 malloc_info() 这两个函数,可显示 process 的 heap 信息

延伸阅读

  • 如何实现一个 malloc(https://kb.cnblogs.com/page/512454/
  • c malloc/free 初探 (https://descent-incoming.blogspot.com/2015/06/c-mallocfree.html)
  • 用 C 语言编写一个简单的垃圾回收器(https://blog.csdn.net/lxw907304340/article/details/44420119)

原文: Writing a Simple Garbage Collector in C

https://blog.csdn.net/lxw907304340/article/details/44420119

https://sourceware.org/gdb/onlinedocs/gdb/Target-Description-Format.html

malloc: first-fit => https://github.com/jserv/mini-arm-os/blob/master/07-Threads/malloc.c

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码