C++ 什么是分段错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2346806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:09:23  来源:igfitidea点击:

What is a segmentation fault?

c++csegmentation-fault

提问by Rajendra Uppal

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

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

回答by zoul

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 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 the memory management, there is no principial difference between segfaults in C and C++.

分段错误是由于访问“不属于您”的内存而导致的一种特定错误。它是一种辅助机制,可防止您破坏内存并引入难以调试的内存错误。每当您遇到段错误时,您就知道自己在内存方面做错了——访问已被释放的变量、写入内存的只读部分等。在大多数让您搞砸的语言中,段错误本质上是相同的在内存管理方面,C 和 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:

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

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 any more, like here:

悬空指针指向一个不再存在的东西,比如这里:

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

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

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

回答by konrad.kruczynski

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).

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

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 mappedto physical one at all.

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

And all of this with respect to virtual memory systems.

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

回答by Ignacio Vazquez-Abrams

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.

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

回答by Component 10

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

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

  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++.)
  1. 在正确初始化之前使用
  2. 在它们指向的内存被重新分配或删除后使用。
  3. 在索引超出数组边界的索引数组中使用。这通常仅在您对传统数组或 c 字符串进行指针数学运算时,而不是基于 STL/Boost 的集合(在 C++ 中)。

回答by Orhan Cinar

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).

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

回答by Alejo Bernardin

Segmentation faultis 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.

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

The solution in this case, change the RAM.

在这种情况下的解决方案是更改 RAM。

edit:

编辑:

Here there is a reference: Segmentation fault by hardware

这里有一个参考:Segmentation fault by hardware

回答by Roy

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

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

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.

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

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)
  • 取消引用 NULL 指针——这是内存管理硬件的特殊情况
  • 试图访问一个不存在的内存地址(在进程的地址空间之外)
  • 尝试访问程序无权访问的内存(例如进程上下文中的内核结构)
  • 尝试写入只读内存(如代码段)

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.)

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

  • 取消引用或分配给已释放的指针(悬空指针,指向已释放/解除分配/删除的内存)

  • 缓冲区溢出。

  • 堆栈溢出。

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

回答by Sohail xIN3N

Segmentation faultoccurs 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) problemmeans 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

回答by FilipeCanatto

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.

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

回答by PHP Worm...

"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].

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

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).

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