段错误(核心已转储)的原因

一、什么是段错误?

一旦一个程序发生了越界访问,cpu 就会产生相应的保护,于是 segmentation fault 就出现了,通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的,还有可能是缺少文件或者文件损坏。

二、段错误产生的原因

下面是一些典型的段错误的原因: 非关联化空指针——这是特殊情况由内存管理硬件 试图访问一个不存在的内存地址(在进程的地址空间) 试图访问内存的程序没有权利(如内核结构流程上下文) 试图写入只读存储器(如代码段)

1、访问不存在的内存地址

在C代码,分割错误通常发生由于指针的错误使用,特别是在C动态内存分配。非关联化一个空指针总是导致段错误,但野指针和悬空指针指向的内存,可能会或可能不会存在,而且可能或不可能是可读的还是可写的,因此会导致瞬态错误。

#include <stdio.h>

int main (void)
{
    int *ptr = NULL;
    *ptr = 0;
    return 0;
}
输出结果:
段错误(核心已转储)

现在,非关联化这些变量可能导致段错误:非关联化空指针通常会导致段错误,阅读时从野指针可能导致随机数据但没有段错误,和阅读从悬空指针可能导致有效数据,然后随机数据覆盖。

2、访问系统保护的内存地址

#include <stdio.h>

int main (void)
{
    int *ptr = (int *)0;
    *ptr = 100;
    return 0;
}
输出结果:
段错误(核心已转储)

3、访问只读的内存地址

写入只读存储器提出了一个 segmentation fault,这个发生在程序写入自己的一部分代码段或者是只读的数据段,这些都是由操作系统加载到只读存储器。

#include <stdio.h>
#include <string.h>

int main (void)
{
    char *ptr = "test";
    strcpy (ptr, "TEST");
    return 0;
}
输出结果:
段错误(核心已转储)
#include <stdio.h>

int main (void)
{
    char *ptr = "hello";
    *ptr = ‘H‘;
    return 0;
}
输出结果:
段错误(核心已转储)

上述例子ANSI C代码通常会导致段错误和内存保护平台。

它试图修改一个字符串文字,这是根据ANSI C标准未定义的行为。

大多数编译器在编译时不会抓,而是编译这个可执行代码,将崩溃。

包含这个代码被编译程序时,字符串“hello”位于rodata部分程序的可执行文件的只读部分数据段。

当加载时,操作系统与其他字符串和地方常数只读段的内存中的数据。

当执行时,一个变量 ptr 设置为指向字符串的位置,并试图编写一个H字符通过变量进入内存,导致段错误。

编译程序的编译器不检查作业的只读的位置在编译时,和运行类unix操作系统产生以下运行时发生 segmentation fault。

#include <stdio.h>

int main (void)
{
    char ptr[] = "hello";
    ptr[0] = ‘H‘;
    return 0;
}

即使不能修改字符串(相反,这在C标准未定义行为),在C char *类型,所以没有隐式转换原始代码,在c++的 const char *类型,因此有一个隐式转换,所以编译器通常会抓住这个特定的错误。

4、空指针废弃

因为是一个很常见的程序错误空指针废弃(读或写在一个空指针,用于C的意思是“没有对象指针”作为一个错误指示器),大多数操作系统内存访问空指针的地址,这样它会导致段错误。

#include <stdio.h>

int main (void)
{
    int *ptr = NULL;
    printf ("%d\n", *ptr);
    return 0;
}
输出结果:
段错误(核心已转储)

这个示例代码创建了一个空指针,然后试图访问它的值(读值)。在运行时在许多操作系统中,这样做会导致段错误。

非关联化一个空指针,然后分配(写一个值到一个不存在的目标)也通常会导致段错误。

#include <stdio.h>

int main (void)
{
    int *ptr = NULL;
    *ptr = 1;
    return 0;
}
输出结果:
段错误(核心已转储)

下面的代码包含一个空指针,但当编译通常不会导致段错误,值是未使用的。因此,废弃通常会被优化掉,死代码消除。

#include <stdio.h>

int main (void)
{
    int *ptr = NULL;
    *ptr;
    return 0;
}

还有,比如malloc 动态分配内存,释放、置空完成后,不可再使用该指针。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char* str=(char* )malloc(100);
    if(*str)
    {
        return;
    }
    strcpy(str,"hello");
    printf("%s\n",str);
    free(str);
    str=NULL;
    strcpy(str,"abcdef");
    return 0;
}
输出结果:
hello
段错误 (核心已转储)

5、堆栈溢出

#include <stdio.h>
#include <string.h>

int main (void)
{
    main ();
    return 0;
}
输出结果:
段错误(核心已转储)

上述例子的无限递归,导致的堆栈溢出会导致段错误,但无线递归未必导致堆栈溢出,优化执行的编译器和代码的确切结构。

在这种情况下,遥不可及的代码(返回语句)行为是未定义的。

因此,编译器可以消除它,使用尾部调用优化,可能导致没有堆栈使用。其他优化可能包括将递归转换成迭代,给出例子的结构功能永远会导致程序运行,虽然可能不是其他堆栈溢出。

6、内存越界(数组越界,变量类型不一致等)

#include <stdio.h>

int main (void)
{
    char test[10];
    printf ("%c\n", test[100000]);
    return 0;
}
输出结果:
段错误(核心已转储)

转自:

--------------------- 作者:聚优致成 来源:CSDN 原文:https://blog.csdn.net/qq_29350001/article/details/53780697

原文地址:https://www.cnblogs.com/zzdbullet/p/9892110.html

时间: 2024-10-10 10:11:32

段错误(核心已转储)的原因的相关文章

Linux下运行C++程序出现&quot;段错误(核心已转储)&quot;的原因

今天写程序出现了“段错误(核心已转储)"的问题,查了一下资料,加上自己的实践,总结了以下几个方面的原因. 1.内存访问出错  这类问题的典型代表就是数组越界. 2.非法内存访问 出现这类问题主要是程序试图访问内核段内存而产生的错误. 3.栈溢出  Linux默认给一个进程分配的栈空间大小为8M.c++申请变量时,new操作申请的变量在堆中,其他变量一般在存储在栈中.  因此如果你数组开的过大变会出现这种问题.  首先我们先看一下系统默认分配的资源: 1 ulimit -a 可以看到默认分配的栈大

段错误 核心已转储尝试解决

1.在进行 gdb python r XX.py where 调试时,报出以下错误: 1)每次运行都开38个线程,是否是线程超载[New Thread 0x7ffff2fd2700 (LWP 7415)] [New Thread 0x7ffff27d1700 (LWP 7416)] [New Thread 0x7fffeffd0700 (LWP 7417)] [New Thread 0x7fffeb7cf700 (LWP 7418)] [New Thread 0x7fffe8fce700 (LW

linux下C编程free()时出现飘忽诡异的段错误(核心已转储)问题

先说一下问题现场. 代码如下 free(volthisframe->Tops); free(volthisframe->Bots); printf("what\n"); free(volthisframe->SCTops); free(volthisframe->SCBots); 运行时出现段错误,"what"随机出现,也就是说可能是打印前出现段错误,也可能是打印后出现段错误.但最终定位就在这几行free里面. 人格保证,各个指针都有初始化,

C++中单项链表的结点删除问题——为什么我的链表编译能过,但是运行的时候显示:*** Error in `./list&#39;: free(): invalid pointer: 0x08ba20cc *** 已放弃 (核心已转储)

1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 5 struct student{ 6 int my_id; 7 char name[20]; 8 int my_age; 9 int my_score; 10 student *next = nullptr; 11 student() = default; 12 student(int id,const char *n,int age,int sco

GCC 4.6.3段错误(核心已转储)

//串口相关的头文件 #include <stdio.h>      /*标准输入输出定义*/ #include <stdlib.h>     /*标准函数库定义*/ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>      /*文件控制定义*/ #include <unistd.h>     /*标准输入输出定义*/ #include <errno

结构体指针之 段错误 具体解释(segmentation fault)

一个网友问了我一个问题.一个C程序执行出现了段错误,这个问题非常好.非常多刚開始学习的人都easy犯这个错误,详细代码例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 这个编译没有问题,可是执行是段错误    Segmentation fault 由于你定义了一个结构体指针p.用来指向此类

PAT 1024 科学计数法 段错误

科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式[+-][1-9]"."[0-9]+E[+-][0-9]+,即数字的整数部分只有1位,小数部分至少有1位,该数字及其指数部分的正负号即使对正数也必定明确给出. 现以科学计数法的格式给出实数A,请编写程序按普通数字表示法输出A,并保证所有有效位都被保留. 输入格式: 每个输入包含1个测试用例,即一个以科学计数法表示的实数A.该数字的存储长度不超过9999字节,且其指数的绝对值不超过9999. 输出格式: 对每个测

linux Ubuntu(Segmentation fault)段错误出现原因及调试方法

  在linux下编译了一个程序,尝试运行的时候出现: Segmentation fault (core dumped) 初步确认为...完全不知道是什么玩意. 于是找度娘了. ---------------------------------------------------------------------------- 出现原因 原来这个东西叫做段错误,就程序运行的时候出现内存错误.有很多原因会导致这样的内存错误,但是应该把这些问题归结于程序的错误,那么程序是出现了什么样的错误了呢,为

Linux环境下段错误的产生原因及调试方法小结(转)

最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且 项目工程庞大复杂,出现了不少问题,其中遇到最多.花费时间最长的问题就是著名的“段错误”(Segmentation Fault).借此机会系统学习了一下,这里对Linux环境下的段错误做个小结,方便以后同类问题的排查与解决. 1. 段错误是什么 一句话来说,段错误是指访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址.访问了系统保护的内存地址.访问了只读的内存地址等等情况.这里贴一个对于“段