你的哪些骚操作会导致Segmentation Fault前言如果你是一个写过一些C程序的同学,那么很大可能你会遇到魔幻的segmentation fault,可能一时间抓耳挠腮,本篇文章主要介绍一些常见的导致segmentation fault的代码问题,希望能够帮助大家快速定位问题!
出现Segmentation Fault的常见操作写只读数据#include <stdio.h>char* str= "hello world";int main() {printf("%s\n", str);*str = '1';return 0;}
在上面的程序当中 , str
是一个全局变量,一个指向只读数据hello world
的指针,因为指向的数据存放在只读数据区,如下图所示(rodata区域):
文章插图
数组下标越界
#include <stdio.h>int main() {int arr[10];arr[1 << 20] = 100; // 会导致 segmentation faultprintf("arr[n] = %d\n", arr[1 << 20]); // 会导致 segmentation faultreturn 0;}
栈溢出 stakc_overflow我们可以使用ulimit -a
命令查看,系统的一些参数设置 , 比如说栈的最大大?。??code git:(main) ? ulimit -a-t: cpu time (seconds)unlimited-f: file size (blocks)unlimited-d: data seg size (kbytes)unlimited-s: stack size (kbytes)8192-c: core file size (blocks)0-m: resident set size (kbytes)unlimited-u: processes2061578-n: file descriptors1048576-l: locked-in-memory size (kbytes)65536-v: address space (kbytes)unlimited-x: file locksunlimited-i: pending signals2061578-q: bytes in POSIX msg queues819200-e: max nice0-r: max rt priority0-N 15:unlimited
上面的参数你可以通过重新编译linux进行更改 。在上面的参数当中我们的栈能够申请的最大空间等于8192kb = 8M
, 我们现在写一个程序来测试一下:#include <stdio.h>void stakc_overflow(int times) {printf("times = %d\n", times);char data[1 << 20]; // 每次申请 1 Mega 数据stakc_overflow(++times);}int main() {stakc_overflow(1);return 0;}
上面的程序输出结果如下所示:【你的哪些骚操作会导致Segmentation Fault😂】
文章插图
当我们低8次调用
stakc_overflow
函数的时候 , 程序崩溃了,因为这个时候我们再申请数组的时候,就一定会超过8M,因为在前面的 7 次调用当中已经申请的 7M 的空间,除此之外还有其他的数据需要使用一定的栈空间 , 因此会有栈溢出,然后报 segmentation failt 错误 。解引用空指针或者野指针
#include <stdio.h>int main() {int* p;printf("%d\n", *p);return 0;}
当我们去解引用一个空指针或者一个野指针的时候就汇报segmentation fault,其实本质上还是解引用访问的页面没有分配或者没有权限访问,比如下面代码我们可以解引用一个已经被释放的空间 。#include <stdio.h>#include <stdint.h>uint64_t find_rbp() {// 这个函数主要是得到寄存器 rbp 的值uint64_t rbp;asm("movq %%rbp, %0;":"=m"(rbp)::);return rbp;}int main() {uint64_t rbp =find_rbp();printf("rbp = %lx\n", rbp);// long* p = 0x7ffd4ea724a0;printf("%ld\n", *(long*)rbp);return 0;}
上面的代码当中我们调用函数 find_rbp
,得到这个函数对应的寄存器 rbp 的值 , 当这个函数调用返回的时候,这个函数的栈帧会被摧毁 , 也就是说 rbp 指向的位置程序已经没有使用了,但是上面的程序不会产生 segmentation fault ,其中最主要的原因就是解引用的位置的页面我们已经分配了,而且我们有读权限 , 而且我们也有写权限,我们甚至可以给 rbp 指向的位置赋值,像下面那样 , 程序也不会崩溃 。#include <stdio.h>#include <stdint.h>uint64_t find_rbp() {uint64_t rbp;asm("movq %%rbp, %0;":"=m"(rbp)::);return rbp;}int main() {uint64_t rbp =find_rbp();printf("rbp = %lx\n", rbp);// long* p = 0x7ffd4ea724a0;printf("%ld\n", *(long*)rbp);*(long*)rbp = 100; // 给指向的位置进行复制操作return 0;}
解引用已经释放的内存#include <stdlib.h>int main() {int* ptr = (int*)malloc(sizeof(int));free(ptr);*ptr = 10;return 0;}
其实上面的代码不见得一定会产生 sementation fault 因为我们使用的libc给我们提供的 free 和 malloc 函数 , 当我们使用 free 函数释放我们的内存的时候,这部分内存不一定就马上还给操作系统了,因此在地址空间当中这部分内存还是存在的,因此是可以解引用的 。其他方式我相信你肯定还有很多其他的方式去引起 sementation fault 的,嗯相信你?。。?
造成 sementation failt 的原因主要有以下两大类:
推荐阅读
- 三星Neo QLED电视有哪些优点_三星Neo QLED电视使用评测
- 原神赛诺传说任务哪些地方有宝箱
- 骁龙888 Plus和骁龙888的区别_有哪些升级
- 原神巨大叶片迎风转动礼物宝箱位置在哪些地方
- 王者荣耀S29赛季中路哪些英雄好上分
- 小米10s缺点和不足_小米10s缺点有哪些
- YOLOv5】LabVIEW+OpenVINO让你的YOLOv5在CPU上飞起来
- 原神3.2版本最新爆料内容有哪些
- CSGO控制台指令有哪些 csgo时间无限指令
- 明日方舟明椒技能有哪些