什么是分段错误?
什么是分段错误? C和C++有什么不同吗?分段错误和悬空指针有何关系?
What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(17)
分段错误是由于访问“不属于您”的内存而导致的一种特定错误。它是一种辅助机制,可以防止您破坏内存并引入难以调试的内存错误。每当你遇到段错误时,你就知道你在内存方面做错了——访问已经释放的变量、写入内存的只读部分等。在大多数语言中,段错误本质上是相同的,这会让你陷入混乱。对于内存管理,C 和 C++ 中的段错误之间没有主要区别。
产生段错误的方法有很多,至少在 C(++) 等较低级语言中是这样。获得段错误的常见方法是取消引用空指针:
当您尝试写入标记为只读的内存部分时,会发生另一个段错误:
悬空指针指向不再存在的事物,如下所示:
指针
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:
Another segfault happens when you try to write to a portion of memory that was marked as read-only:
Dangling pointer points to a thing that does not exist anymore, like here:
The pointer
p
dangles because it points to the character variablec
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.值得注意的是,分段错误不是由直接访问另一个进程内存引起的(这是我有时听到的),因为这是不可能的。使用虚拟内存,每个进程都有自己的虚拟地址空间,并且无法使用任何指针值访问另一个进程。例外情况是共享库,它们是将相同的物理地址空间映射到(可能)不同的虚拟地址和内核内存,甚至在每个进程中以相同的方式映射(我认为是为了避免系统调用上的 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.
分段错误是由对进程未在其描述符表中列出的页面的请求或对已列出的页面的无效请求(例如,对只读页面的写入请求)引起的。
悬空指针是可能指向也可能不指向有效页面的指针,但确实指向“意外”内存段。
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.
老实说,正如其他发帖者提到的,维基百科有一篇关于此的非常好的文章所以看看那里。< /a> 这种类型的错误非常常见,通常称为其他错误,例如访问冲突或一般保护错误。
它们在 C、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
根据 维基百科:
According to Wikipedia:
分段错误也是由硬件故障引起的,在本例中是 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
维基百科的 Segmentation_fault 页面对此有非常好的描述,只是指出了原因和原因。查看 wiki 以获取详细说明。
在计算中,分段错误(通常简称为 segfault)或访问冲突是由具有内存保护的硬件引发的错误,通知操作系统 (OS) 有关内存访问冲突的信息。
以下是分段错误的一些典型原因:
这些通常是由导致无效内存访问的编程错误引起的:
取消引用或分配给未初始化的指针(野指针,指向随机内存地址)
取消引用或分配给已释放的指针(悬空指针,指向 未初始化的指针)已被释放/释放/删除)
缓冲区溢出。
缓冲区
堆栈溢出。
尝试执行未正确编译的程序。 (尽管存在编译时错误,某些编译器仍会输出可执行文件。)
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:
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.)
当进程(程序的运行实例)尝试访问其他进程正在使用的只读内存地址或内存范围或访问不存在(无效)的内存地址时,分段错误发生。
悬空引用(指针)问题意味着尝试访问其内容已从内存中删除的对象或变量,例如:
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:
简单来说:分段错误是操作系统向程序发送信号
表示已检测到非法内存访问并提前终止程序以防止
内存被损坏。
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.
答案中对“分段错误”有几个很好的解释,但是由于分段错误通常会转储内存内容,因此我想分享分段错误(核心)中“核心转储”部分之间的关系已转储) 内存来自:
摘自此处。
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:
Taken from here.
您可能正在使用错误的数据类型访问计算机内存。您的情况可能类似于下面的代码:
'asd' ->是字符链而不是单个字符
char
数据类型。因此,将其存储为字符会导致分段错误。 在错误的位置存储一些数据。将此
字符串
或字符链存储为单个字符
正在尝试将方钉放入圆孔中。由于信号而终止:SEGMENTATION FAULT (11)
Segm。错误就像试图在水下呼吸一样,你的肺不是为此而生的。为整数保留内存然后尝试将其作为另一种数据类型进行操作根本不起作用。
You might be accessing the computer memory with the wrong data type. Your case might be like the code below:
'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 singlechar
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.
“分段错误”意味着您试图访问您无权访问的内存。
第一个问题是你的 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).
分段错误
的简单含义是您正在尝试访问一些不属于您的内存。当我们尝试在只读内存位置读取和/或写入任务或尝试释放内存时,会发生分段错误。换句话说,我们可以将其解释为某种内存损坏。下面我提到了程序员所犯的导致
分段错误
的常见错误。scanf()
(忘记输入&
)。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
.scanf()
in wrong way(forgot to put&
).printf()
andscanf()
'考虑以下代码片段,
SNIPPET 1
SNIPPET 2
如果您问这个问题,我假设您知道这些函数的含义:
malloc()
和sizeof()
。既然事情已经解决了,
SNIPPET 1 会抛出分段错误错误。
而 SNIPPET 2 不会。
原因如下。
代码片段的第一行创建一个变量(*number)来存储其他变量的地址,但在本例中它被初始化为 NULL。
另一方面,
片段二的第二行创建相同的变量(*number)来存储其他变量的地址,在这种情况下,它被赋予一个内存地址(因为 malloc() 是 C/C++ 中的一个函数,它返回一个内存地址计算机)
重点是您不能将水放入未购买的碗或已购买但未经您授权使用的碗中。
当您尝试这样做时,计算机会收到警报并抛出 SegFault 错误。
您应该只使用接近低级的语言(例如 C/C++)来面对此错误。其他高级语言中有一个抽象可以确保您不会犯此错误。
同样重要的是要了解分段错误不是特定于语言的。
Consider the following snippets of Code,
SNIPPET 1
SNIPPET 2
I'd assume you know the meaning of the functions:
malloc()
andsizeof()
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.
分段错误的定义已经足够多了,我想引用一些我在编程时遇到的例子,这些例子可能看起来很愚蠢,但会浪费很多时间。
printf
中的参数类型不匹配时,您可能会遇到分段错误:输出:
分段错误(SIGSEGV)
输出:
分段错误 (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.
printf
:output :
Segmentation Fault (SIGSEGV)
output :
Segmentation Fault (SIGSEGV)
当一个进程(程序的运行实例)试图访问另一个进程正在使用的只读内存地址或内存范围或访问不存在的内存地址时,就会发生分段错误。
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
当程序尝试访问不存在的内存位置或尝试以不允许的方式访问内存位置时,就会发生分段错误或访问冲突。
这里i[1000]不存在,所以出现段错误。
分段错误的原因:
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.
Here i[1000] not exist, so segfault occurs.
Causes of segmentation fault: