Santi92 Asked: 2020-12-04 10:03:50 +0800 CST 2020-12-04 10:03:50 +0800 CST 2020-12-04 10:03:50 +0800 CST 段违规是什么意思? 772 很多时候在C中编程,遇到分段错误消息,这是什么意思,为什么会发生? c 4 Answers Voted Best Answer Angel Angel 2020-12-05T02:42:38+08:002020-12-05T02:42:38+08:00 分段错误 - 段违规。 这是什么意思? 这是一种非常常见的运行时错误类型 C/C++。 当程序运行时,你的系统报告系统抛出“segmentation violation”,说明你的程序试图访问一个不允许访问的内存区域。换句话说,您试图访问超出操作系统(Unix GNU/Linux 等)为您的程序分配的限制的部分内存。 为什么会发生 此问题的一些常见原因: 运算符"&"(方向/地址)和"*" (间接/取消引用)的错误使用 printf 或 scanf 语句中的控制字符串格式错误 格式控制字符串必须具有相同数量的要打印或读取的转换说明符(%'s)和参数,并且说明符必须与要打印或读取的变量的类型相匹配。这适用于 fprintf 和 fscanf 以及 printf 和 scanf。 忘记"&"在 scanf 参数中使用(这种情况是 Elenasys 提到的) scanf 函数将格式控制字符串和要放置要读取的数据的变量的地址作为参数(运算符"&"用于提供变量的地址)。"&"在 scanf 调用中忘记使用每个变量是很常见的。省略"&"可能会导致分段违规。 超出数组/向量或类似限制的访问:尝试访问数组的下标,其值小于其最低元素的索引或大于其最高元素的索引。 在访问指针之前初始化指针时出错:必须为“指针”变量分配一个有效的内存地址。 int *ip; std::cout << *ip << std::endl; //usar un puntero no inicializado 即使您的程序可以访问部分内存,也试图不正确地访问它。 char *str = "string";// static array de caracteres, sin nombre/id // este array se crea en modo "read-only memory" // como solo lectura str[0] = 'n'; 尝试访问已从内存中清除的对象或变量,例如: int *pArrI = new int[9];//solicitamos en el heap delete[] pArrI; //eliminamos std::cout << pArrI[1]; //intentamos acceder a una parte inexistente ninjalj 2020-12-04T10:55:14+08:002020-12-04T10:55:14+08:00 在具有虚拟内存的 Unix 系统上,每个进程都有可以访问的内存区域。例如,在 Linux 上,您可以通过读取虚拟文件来查看进程的虚拟内存区域 (VMA) /proc/<pid>/maps: $ cat /proc/self/maps 08048000-0804c000 r-xp 00000000 03:04 1553592 /bin/cat 0804c000-0804d000 rw-p 00003000 03:04 1553592 /bin/cat 08d7c000-08d9d000 rw-p 08d7c000 00:00 0 [heap] b7da2000-b7da3000 rw-p b7da2000 00:00 0 b7da3000-b7eeb000 r-xp 00000000 03:04 2190352 /lib/libc-2.6.1.so b7eeb000-b7eed000 r--p 00148000 03:04 2190352 /lib/libc-2.6.1.so b7eed000-b7eee000 rw-p 0014a000 03:04 2190352 /lib/libc-2.6.1.so b7eee000-b7ef2000 rw-p b7eee000 00:00 0 b7f14000-b7f15000 r-xp b7f14000 00:00 0 [vdso] b7f15000-b7f31000 r-xp 00000000 03:04 2190353 /lib/ld-2.6.1.so b7f31000-b7f32000 r--p 0001b000 03:04 2190353 /lib/ld-2.6.1.so b7f32000-b7f33000 rw-p 0001c000 03:04 2190353 /lib/ld-2.6.1.so bfa1d000-bfa32000 rw-p bffeb000 00:00 0 [stack] 如您所见,您将获得一个内存区域列表,以及相关权限(r-read、w-write、x-execute)。 如果一个进程试图访问一个不在上一个列表中的内存区域,或者试图访问一个它没有权限的访问,处理器的 MMU(内存管理单元)会产生一个异常,内核会处理这个异常,参考上面的列表,最后内核会向SIGSEGV进程发送信号。 的默认操作SIGSEGV是通过生成核心转储来终止进程。 还有另一个相关信号 ,SIGBUS它对应于总线错误。在某些处理器上,SIGBUS如果尝试访问未对齐的地址(例如,如果尝试访问不可被 4 字节整除的地址处的 4 字节字),则会获得它。另一个可能的原因SIGBUS是如果其中一个区域对应于内存映射的物理设备,并且对该物理地址的访问失败。 Jorgesys 2020-12-04T10:08:20+08:002020-12-04T10:08:20+08:00 这是一个通常在以下情况下发生的概念: 某个程序试图访问它没有访问权限的内存区域。 在互联网上寻找您拥有的定义: 访问违规。 它被定义为对访问您无权查看或修改的信息或程序的失败尝试的访问冲突(英文为violation of the segment 或access violation and segmentation fault)。此消息可能由软件配置、编程器或硬件故障引起,前两种最为常见。 对于当今的操作系统,每个进程都有一个或多个系统内存段,可以在其中存储和检索信息。每个进程都可以请求更多或更少的内存(根据需要),并且该请求将被操作系统识别并与授予该进程的内存部分进行比较。通常,请求内存的进程是唯一可以读取或修改它的进程。 当一个进程在没有权限的情况下尝试访问分配给另一个应用程序的部分内存,或者未使用的内存区域时,就会发生访问冲突。它通常是由于编程错误(例如杂散指针)而发生的。可能发生分段错误的另一种方式是内存物理损坏,因为某些程序将写入内存,然后尝试访问该数据,但是当内存发生故障时,数据可能已被擦除,因此程序将考虑该内存地址为空,即未使用,会抛出错误。 假设在以下程序中我们省略了如何生成它的常见示例&: #include <stdio.h> int main () { int i; printf ("introduce tu edad: "); scanf ("%d",i); //genera violación de segmento! printf ("Miss Elena, tu edad es: , %d.\n",i); return 0; } 在线上: scanf ("%d",&i); 然后发生访问冲突。 Fabián Heredia Montiel 2020-12-04T10:09:36+08:002020-12-04T10:09:36+08:00 当进程试图访问不属于它的内存或执行它没有权限的操作时,就会发生段错误。常见的例子是: 尝试访问已被释放的变量。 尝试写入只读变量。
分段错误 - 段违规。
这是什么意思?
这是一种非常常见的运行时错误类型
C/C++
。当程序运行时,你的系统报告系统抛出“segmentation violation”,说明你的程序试图访问一个不允许访问的内存区域。换句话说,您试图访问超出操作系统(Unix GNU/Linux 等)为您的程序分配的限制的部分内存。
为什么会发生
此问题的一些常见原因:
"&"
(方向/地址)和"*"
(间接/取消引用)的错误使用格式控制字符串必须具有相同数量的要打印或读取的转换说明符
(%'s)
和参数,并且说明符必须与要打印或读取的变量的类型相匹配。这适用于 fprintf 和 fscanf 以及 printf 和 scanf。"&"
在 scanf 参数中使用(这种情况是 Elenasys 提到的)scanf 函数将格式控制字符串和要放置要读取的数据的变量的地址作为参数(运算符
"&"
用于提供变量的地址)。"&"
在 scanf 调用中忘记使用每个变量是很常见的。省略"&"
可能会导致分段违规。在访问指针之前初始化指针时出错:必须为“指针”变量分配一个有效的内存地址。
即使您的程序可以访问部分内存,也试图不正确地访问它。
尝试访问已从内存中清除的对象或变量,例如:
在具有虚拟内存的 Unix 系统上,每个进程都有可以访问的内存区域。例如,在 Linux 上,您可以通过读取虚拟文件来查看进程的虚拟内存区域 (VMA)
/proc/<pid>/maps
:如您所见,您将获得一个内存区域列表,以及相关权限(
r
-read、w
-write、x
-execute)。如果一个进程试图访问一个不在上一个列表中的内存区域,或者试图访问一个它没有权限的访问,处理器的 MMU(内存管理单元)会产生一个异常,内核会处理这个异常,参考上面的列表,最后内核会向
SIGSEGV
进程发送信号。的默认操作
SIGSEGV
是通过生成核心转储来终止进程。还有另一个相关信号 ,
SIGBUS
它对应于总线错误。在某些处理器上,SIGBUS
如果尝试访问未对齐的地址(例如,如果尝试访问不可被 4 字节整除的地址处的 4 字节字),则会获得它。另一个可能的原因SIGBUS
是如果其中一个区域对应于内存映射的物理设备,并且对该物理地址的访问失败。这是一个通常在以下情况下发生的概念:
在互联网上寻找您拥有的定义: 访问违规。
假设在以下程序中我们省略了如何生成它的常见示例
&
:在线上:
然后发生访问冲突。
当进程试图访问不属于它的内存或执行它没有权限的操作时,就会发生段错误。常见的例子是: