什么是分段错误?

发布于 2024-08-23 07:51:50 字数 42 浏览 7 评论 0原文

什么是分段错误? C和C++有什么不同吗?分段错误和悬空指针有何关系?

What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

这个俗人 2024-08-30 07:51:50

分段错误是由于访问“不属于您”的内存而导致的一种特定错误。它是一种辅助机制,可以防止您破坏内存并引入难以调试的内存错误。每当你遇到段错误时,你就知道你在内存方面做错了——访问已经释放的变量、写入内存的只读部分等。在大多数语言中,段错误本质上是相同的,这会让你陷入混乱。对于内存管理,C 和 C++ 中的段错误之间没有主要区别。

产生段错误的方法有很多,至少在 C(++) 等较低级语言中是这样。获得段错误的常见方法是取消引用空指针:

int *p = NULL;
*p = 1;

当您尝试写入标记为只读的内存部分时,会发生另一个段错误:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

悬空指针指向不再存在的事物,如下所示:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

指针p悬空,因为它指向字符变量c,该变量在块结束后不再存在。当您尝试取消引用悬空指针(如 *p='A')时,您可能会遇到段错误。

Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory – accessing a variable that has already been freed, writing to a read-only portion of the memory, etc. Segmentation fault is essentially the same in most languages that let you mess with memory management, there is no principal difference between segfaults in C and C++.

There are many ways to get a segfault, at least in the lower-level languages such as C(++). A common way to get a segfault is to dereference a null pointer:

int *p = NULL;
*p = 1;

Another segfault happens when you try to write to a portion of memory that was marked as read-only:

char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault

Dangling pointer points to a thing that does not exist anymore, like here:

char *p = NULL;
{
    char c;
    p = &c;
}
// Now p is dangling

The pointer p dangles because it points to the character variable c that ceased to exist after the block ended. And when you try to dereference dangling pointer (like *p='A'), you would probably get a segfault.

对风讲故事 2024-08-30 07:51:50

值得注意的是,分段错误不是由直接访问另一个进程内存引起的(这是我有时听到的),因为这是不可能的。使用虚拟内存,每个进程都有自己的虚拟地址空间,并且无法使用任何指针值访问另一个进程。例外情况是共享库,它们是将相同的物理地址空间映射到(可能)不同的虚拟地址和内核内存,甚至在每个进程中以相同的方式映射(我认为是为了避免系统调用上的 TLB 刷新)。诸如 shmat 之类的东西;) - 这些是我认为的“间接”访问。然而,我们可以检查它们通常距离流程代码很远,并且我们通常能够访问它们(这就是它们存在的原因,但是以不正确的方式访问它们会产生分段错误)。

不过,如果以不正确的方式访问我们自己的(进程)内存(例如尝试写入不可写空间),则可能会发生分段错误。但最常见的原因是访问虚拟地址空间中根本没有映射到物理地址空间的部分。

所有这些都与虚拟内存系统有关。

It would be worth noting that segmentation fault isn't caused by directly accessing another process memory (this is what I'm hearing sometimes), as it is simply not possible. With virtual memory every process has its own virtual address space and there is no way to access another one using any value of pointer. Exception to this can be shared libraries which are same physical address space mapped to (possibly) different virtual addresses and kernel memory which is even mapped in the same way in every process (to avoid TLB flushing on syscall, I think). And things like shmat ;) - these are what I count as 'indirect' access. One can, however, check that they are usually located long way from process code and we are usually able to access them (this is why they are there, nevertheless accessing them in a improper way will produce segmentation fault).

Still, segmentation fault can occur in case of accessing our own (process) memory in improper way (for instance trying to write to non-writable space). But the most common reason for it is the access to the part of the virtual address space that is not mapped to physical one at all.

And all of this with respect to virtual memory systems.

还不是爱你 2024-08-30 07:51:50

分段错误是由对进程未在其描述符表中列出的页面的请求或对已列出的页面的无效请求(例如,对只读页面的写入请求)引起的。

悬空指针是可能指向也可能不指向有效页面的指针,但确实指向“意外”内存段。

A segmentation fault is caused by a request for a page that the process does not have listed in its descriptor table, or an invalid request for a page that it does have listed (e.g. a write request on a read-only page).

A dangling pointer is a pointer that may or may not point to a valid page, but does point to an "unexpected" segment of memory.

彼岸花ソ最美的依靠 2024-08-30 07:51:50

老实说,正如其他发帖者提到的,维基百科有一篇关于此的非常好的文章所以看看那里。< /a> 这种类型的错误非常常见,通常称为其他错误,例如访问冲突或一般保护错误。

它们在 C、C++ 或任何其他允许指针的语言中没有什么不同。此类错误通常是由

  1. 在正确初始化之前使用的
  2. 指针以及在重新分配或删除它们指向的内存之后使用的指针引起的。
  3. 用于索引超出数组范围的索引数组。这通常仅在您对传统数组或 C 字符串进行指针数学运算时发生,而不是在基于 STL/Boost 的集合(在 C++ 中)上进行。

To be honest, as other posters have mentioned, Wikipedia has a very good article on this so have a look there. This type of error is very common and often called other things such as Access Violation or General Protection Fault.

They are no different in C, C++ or any other language that allows pointers. These kinds of errors are usually caused by pointers that are

  1. Used before being properly initialised
  2. Used after the memory they point to has been realloced or deleted.
  3. Used in an indexed array where the index is outside of the array bounds. This is generally only when you're doing pointer math on traditional arrays or c-strings, not STL / Boost based collections (in C++.)
極樂鬼 2024-08-30 07:51:50

根据 维基百科

当一个
程序尝试访问内存
不允许的位置
访问,或尝试访问内存
以不允许的方式定位
(例如,尝试写入
只读位置,或覆盖
操作系统的一部分)。

According to Wikipedia:

A segmentation fault occurs when a
program attempts to access a memory
location that it is not allowed to
access, or attempts to access a memory
location in a way that is not allowed
(for example, attempting to write to a
read-only location, or to overwrite
part of the operating system).

我早已燃尽 2024-08-30 07:51:50

分段错误也是由硬件故障引起的,在本例中是 RAM 存储器。这是不太常见的原因,但如果您在代码中没有发现错误,也许内存测试可以帮助您。

这种情况的解决办法是更换内存。

编辑:

这里有一个参考:硬件分段错误

Segmentation fault is also caused by hardware failures, in this case the RAM memories. This is the less common cause, but if you don't find an error in your code, maybe a memtest could help you.

The solution in this case, change the RAM.

edit:

Here there is a reference: Segmentation fault by hardware

谜兔 2024-08-30 07:51:50

维基百科的 Segmentation_fault 页面对此有非常好的描述,只是指出了原因和原因。查看 wiki 以获取详细说明。

在计算中,分段错误(通常简称为 segfault)或访问冲突是由具有内存保护的硬件引发的错误,通知操作系统 (OS) 有关内存访问冲突的信息。

以下是分段错误的一些典型原因:

  • 取消引用 NULL 指针 – 这是内存管理硬件的特殊情况
  • 尝试访问不存在的内存地址(进程的地址空间之外)
  • 尝试访问程序无权访问的内存(例如作为进程上下文中的内核结构)
  • 尝试写入只读内存(例如代码段)

这些通常是由导致无效内存访问的编程错误引起的:

  • 取消引用或分配给未初始化的指针(野指针,指向随机内存地址)

  • 取消引用或分配给已释放的指针(悬空指针,指向 未初始化的指针)已被释放/释放/删除)

  • 缓冲区溢出。

    缓冲区

  • 堆栈溢出。

  • 尝试执行未正确编译的程序。 (尽管存在编译时错误,某些编译器仍会输出可执行文件。)

Wikipedia's Segmentation_fault page has a very nice description about it, just pointing out the causes and reasons. Have a look into the wiki for a detailed description.

In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation.

The following are some typical causes of a segmentation fault:

  • Dereferencing NULL pointers – this is special-cased by memory management hardware
  • Attempting to access a nonexistent memory address (outside process's address space)
  • Attempting to access memory the program does not have rights to (such as kernel structures in process context)
  • Attempting to write read-only memory (such as code segment)

These in turn are often caused by programming errors that result in invalid memory access:

  • Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)

  • Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)

  • A buffer overflow.

  • A stack overflow.

  • Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)

人间☆小暴躁 2024-08-30 07:51:50

当进程(程序的运行实例)尝试访问其他进程正在使用的只读内存地址或内存范围或访问不存在(无效)的内存地址时,分段错误发生。
悬空引用(指针)问题意味着尝试访问其内容已从内存中删除的对象或变量,例如:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here

Segmentation fault occurs when a process (running instance of a program) is trying to access read-only memory address or memory range which is being used by other process or access the non-existent (invalid) memory address.
Dangling Reference (pointer) problem means that trying to access an object or variable whose contents have already been deleted from memory, e.g:

int *arr = new int[20];
delete arr;
cout<<arr[1];  //dangling problem occurs here
枫林﹌晚霞¤ 2024-08-30 07:51:50

简单来说:分段错误是操作系统向程序发送信号
表示已检测到非法内存访问并提前终止程序以防止
内存被损坏。

In simple words: segmentation fault is the operating system sending a signal to the program
saying that it has detected an illegal memory access and is prematurely terminating the program to prevent
memory from being corrupted.

笑,眼淚并存 2024-08-30 07:51:50

答案中对“分段错误”有几个很好的解释,但是由于分段错误通常会转储内存内容,因此我想分享分段错误(核心)中“核心转储”部分之间的关​​系已转储) 内存来自:

大约从 1955 年到 1975 年(半导体内存出现之前),计算机内存的主导技术使用串在铜线上的微小磁性甜甜圈。甜甜圈被称为“铁氧体磁芯”,主存储器被称为“核心存储器”或“核心”。

摘自此处

There are several good explanations of "Segmentation fault" in the answers, but since with segmentation fault often there's a dump of the memory content, I wanted to share where the relationship between the "core dumped" part in Segmentation fault (core dumped) and memory comes from:

From about 1955 to 1975 - before semiconductor memory - the dominant technology in computer memory used tiny magnetic doughnuts strung on copper wires. The doughnuts were known as "ferrite cores" and main memory thus known as "core memory" or "core".

Taken from here.

百思不得你姐 2024-08-30 07:51:50

在计算中,分段错误或访问冲突是由具有内存保护的硬件引发的错误或故障情况,
通知操作系统该软件已尝试访问
内存限制区域。
-WIKIPEDIA

您可能正在使用错误的数据类型访问计算机内存。您的情况可能类似于下面的代码:

#include <stdio.h>

int main(int argc, char *argv[]) {
    
    char A = 'asd';
    puts(A);
    
    return 0;
    
}

'asd' ->是字符链而不是单个字符char数据类型。因此,将其存储为字符会导致分段错误在错误的位置存储一些数据。

将此字符串或字符链存储为单个字符正在尝试将方钉放入圆孔中。

由于信号而终止:SEGMENTATION FAULT (11)

Segm。错误就像试图在水下呼吸一样,你的肺不是为此而生的。为整数保留内存然后尝试将其作为另一种数据类型进行操作根本不起作用。

In computing, a segmentation fault or access violation is a fault, or failure condition, raised by hardware with memory protection,
notifying an operating system the software has attempted to access a
restricted area of memory.
-WIKIPEDIA

You might be accessing the computer memory with the wrong data type. Your case might be like the code below:

#include <stdio.h>

int main(int argc, char *argv[]) {
    
    char A = 'asd';
    puts(A);
    
    return 0;
    
}

'asd' -> is a character chain rather than a single character char data type. So, storing it as a char causes the segmentation fault. Stocking some data at the wrong position.

Storing this string or character chain as a single char is trying to fit a square peg in a round hole.

Terminated due to signal: SEGMENTATION FAULT (11)

Segm. Fault is the same as trying to breath in under water, your lungs were not made for that. Reserving memory for an integer and then trying to operate it as another data type won't work at all.

記柔刀 2024-08-30 07:51:50

“分段错误”意味着您试图访问您无权访问的内存。

第一个问题是你的 main 参数。 main 函数应该是 int main(int argc, char *argv[]) ,并且在访问 argv[1] 之前应该检查 argc 是否至少为 2。

另外,由于您将浮点数传递给 printf (顺便说一句,它在传递给 printf 时会转换为双精度型),因此您应该使用 %f 格式说明符。 %s 格式说明符用于字符串(以“\0”结尾的字符数组)。

"Segmentation fault" means that you tried to access memory that you do not have access to.

The first problem is with your arguments of main. The main function should be int main(int argc, char *argv[]), and you should check that argc is at least 2 before accessing argv[1].

Also, since you're passing in a float to printf (which, by the way, gets converted to a double when passing to printf), you should use the %f format specifier. The %s format specifier is for strings ('\0'-terminated character arrays).

雪化雨蝶 2024-08-30 07:51:50

分段错误的简单含义是您正在尝试访问一些不属于您的内存。当我们尝试在只读内存位置读取和/或写入任务或尝试释放内存时,会发生分段错误。换句话说,我们可以将其解释为某种内存损坏。

下面我提到了程序员所犯的导致分段错误的常见错误。

  • 以错误的方式使用scanf()(忘记输入&)。
int num;
scanf("%d", num);// must use &num instead of num
  • 以错误的方式使用指针。
int *num; 
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
  • 修改字符串文字(指针尝试写入或修改只读存储器。)
char *str;  

//Stored in read only part of data segment
str = "GfG";      

//Problem:  trying to modify read only memory
*(str+1) = 'n';
  • 尝试访问已释放的地址。
// allocating memory to num 
int* num = malloc(8); 
*num = 100; 

// de-allocated the space allocated to num 
free(num); 

// num is already freed there for it cause segmentation fault
*num = 110; 
  • 堆栈溢出 -:堆栈内存不足
  • 访问数组越界'
  • 使用 printf()scanf() 时使用错误的格式说明符'

Simple meaning of Segmentation fault is that you are trying to access some memory which doesn't belong to you. Segmentation fault occurs when we attempt to read and/or write tasks in a read only memory location or try to freed memory. In other words, we can explain this as some sort of memory corruption.

Below I mention common mistakes done by programmers that lead to Segmentation fault.

  • Use scanf() in wrong way(forgot to put &).
int num;
scanf("%d", num);// must use &num instead of num
  • Use pointers in wrong way.
int *num; 
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
  • Modifying a string literal(pointer try to write or modify a read only memory.)
char *str;  

//Stored in read only part of data segment
str = "GfG";      

//Problem:  trying to modify read only memory
*(str+1) = 'n';
  • Try to reach through an address which is already freed.
// allocating memory to num 
int* num = malloc(8); 
*num = 100; 

// de-allocated the space allocated to num 
free(num); 

// num is already freed there for it cause segmentation fault
*num = 110; 
  • Stack Overflow -: Running out of memory on the stack
  • Accessing an array out of bounds'
  • Use wrong format specifiers when using printf() and scanf()'
尽揽少女心 2024-08-30 07:51:50

考虑以下代码片段,

SNIPPET 1

int *number = NULL;
*number = 1;

SNIPPET 2

int *number = malloc(sizeof(int));
*number = 1;

如果您问这个问题,我假设您知道这些函数的含义: malloc()sizeof()

既然事情已经解决了,
SNIPPET 1 会抛出分段错误错误。
而 SNIPPET 2 不会。

原因如下。

代码片段的第一行创建一个变量(*number)来存储其他变量的地址,但在本例中它被初始化为 NULL。
另一方面,
片段二的第二行创建相同的变量(*number)来存储其他变量的地址,在这种情况下,它被赋予一个内存地址(因为 malloc() 是 C/C++ 中的一个函数,它返回一个内存地址计算机)

重点是您不能将水放入未购买的碗或已购买但未经您授权使用的碗中。
当您尝试这样做时,计算机会收到警报并抛出 SegFault 错误。

您应该只使用接近低级的语言(例如 C/C++)来面对此错误。其他高级语言中有一个抽象可以确保您不会犯此错误。

同样重要的是要了解分段错误不是特定于语言的。

Consider the following snippets of Code,

SNIPPET 1

int *number = NULL;
*number = 1;

SNIPPET 2

int *number = malloc(sizeof(int));
*number = 1;

I'd assume you know the meaning of the functions: malloc() and sizeof() if you are asking this question.

Now that that is settled,
SNIPPET 1 would throw a Segmentation Fault Error.
while SNIPPET 2 would not.

Here's why.

The first line of snippet one is creating a variable(*number) to store the address of some other variable but in this case it is initialized to NULL.
on the other hand,
The second line of snippet two is creating the same variable(*number) to store the address of some other and in this case it is given a memory address(because malloc() is a function in C/C++ that returns a memory address of the computer)

The point is you cannot put water inside a bowl that has not been bought OR a bowl that has been bought but has not been authorized for use by you.
When you try to do that, the computer is alerted and it throws a SegFault error.

You should only face this errors with languages that are close to low-level like C/C++. There is an abstraction in other High Level Languages that ensure you do not make this error.

It is also paramount to understand that Segmentation Fault is not language-specific.

月隐月明月朦胧 2024-08-30 07:51:50

分段错误的定义已经足够多了,我想引用一些我在编程时遇到的例子,这些例子可能看起来很愚蠢,但会浪费很多时间。

  1. 在下面的情况下,当printf中的参数类型不匹配时,您可能会遇到分段错误:
#include <stdio.h>
int main(){   
  int a = 5;
  printf("%s",a);
  return 0;
}

输出:分段错误(SIGSEGV)

  1. 当您忘记为指针分配内存,但尝试使用它。
#include <stdio.h> 
typedef struct{
  int a;
} myStruct;   
int main(){
  myStruct *s;
  /* few lines of code */
  s->a = 5;
  return 0;
}

输出:分段错误 (SIGSEGV)

There are enough definitions of segmentation fault, I would like to quote few examples which I came across while programming, which might seem like silly mistakes, but will waste a lot of time.

  1. You can get a segmentation fault in below case while argument type mismatch in printf:
#include <stdio.h>
int main(){   
  int a = 5;
  printf("%s",a);
  return 0;
}

output : Segmentation Fault (SIGSEGV)

  1. When you forgot to allocate memory to a pointer, but try to use it.
#include <stdio.h> 
typedef struct{
  int a;
} myStruct;   
int main(){
  myStruct *s;
  /* few lines of code */
  s->a = 5;
  return 0;
}

output : Segmentation Fault (SIGSEGV)

残月升风 2024-08-30 07:51:50

当一个进程(程序的运行实例)试图访问另一个进程正在使用的只读内存地址或内存范围或访问不存在的内存地址时,就会发生分段错误。

seg错误,当类型不匹配时

在此处输入图像描述

Segmentation fault occurs when a process (running instance of a program) is trying to access a read-only memory address or memory range which is being used by another process or access the non-existent memory address.

seg fault,when type gets mismatched

enter image description here

九公里浅绿 2024-08-30 07:51:50

当程序尝试访问不存在的内存位置或尝试以不允许的方式访问内存位置时,就会发生分段错误或访问冲突。

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

这里i[1000]不存在,所以出现段错误。

分段错误的原因:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).

A segmentation fault or access violation occurs when a program attempts to access a memory location that is not exist, or attempts to access a memory location in a way that is not allowed.

 /* "Array out of bounds" error 
   valid indices for array foo
   are 0, 1, ... 999 */
   int foo[1000];
   for (int i = 0; i <= 1000 ; i++) 
   foo[i] = i;

Here i[1000] not exist, so segfault occurs.

Causes of segmentation fault:

it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.

De-referencing NULL pointers – this is special-cased by memory management hardware.

Attempting to access a nonexistent memory address (outside process’s address space).

Attempting to access memory the program does not have rights to (such as kernel structures in process context).

Attempting to write read-only memory (such as code segment).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文