无效的 Read/Write 会导致 SIGBUS 错误吗?
Can invalid Read/Write cause SIGBUS Error?
编辑 1:示例程序的平台是 x86_64。
编辑 2: 我正在编辑它以便更好地理解。下面是两个不同的问题。第一个问题是 invalid read/write 会导致 SIGBUS 吗?第二个问题是 Valgrind 对 SIGBUS 分析有用吗?。示例代码用于第二个问题以支持我的观点,即 Valgrind 在 SIGBUS 错误的情况下根本没有用。我这里可能是错的。
实际情况: 我们有一个屏幕 reader 应用程序在连续测试 2 天后崩溃(一次由于 SIGBUS 而崩溃)。我有一个 coredump 文件,但我没有正确的二进制和调试包。所以基本上我必须在不同的二进制文件中测试它,并且由于调试包不匹配,coredump 在 gdb 中无法正常工作。在 Valgrind 分析期间,我可以在 screen-reader 模块中看到一些无效的 read/write。我的队友建议通过修复这些无效的 read/write 将解决此问题,但我认为它不会解决它。以下是我对这两种信号的理解。
SIGSEGV: 地址有效但 read/write 权限不存在。
SIGBUS:地址本身无效(CPU由于对齐错误等原因无法找到地址)
我有一个关于 SIGBUS 信号的问题。我在堆栈溢出上搜索过类似的问题,但没有找到这个问题的明确答案。
无效read/write会导致总线错误(SIGBUS)吗?.
我的理解是,无效的 Read/Write 总是会导致分段错误 (SIGSEGV),修复总线错误的最佳方法是在应用程序上使用 运行 gdb。发生总线错误时的 Valgrind 分析根本没有帮助。下面的代码更详细地解释了这一点。
#include<stdlib.h>
#include<stdio.h>
typedef struct {
char *name;
int val;
}data;
void fun1()
{
data *ptr = malloc(sizeof(data));
ptr->val = 100;
ptr->name = "name in structure";
printf("val:%d name:%s\n",ptr->val,ptr->name);
free(ptr);
ptr = NULL;
printf("val:%d name:%s\n",ptr->val,ptr->name); //SIGSEGV
return;
}
int fun2()
{
#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__("pushf\norl [=11=]x40000,(%esp)\npopf");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("pushf\norl [=11=]x40000,(%rsp)\npopf");
# endif
#endif
char *cptr = malloc(sizeof(int) + 1);
char *optr = cptr;
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
free(optr);
return 0;
}
void fun()
{
fun2();
//fun1();
}
int main()
{
fun();
return 0;
}
在分段错误的情况下,Valgrind 报告将包含有关导致崩溃的代码的详细信息,但在 SIGBUS 崩溃的情况下,我在 Valgrind 报告中没有找到任何此类详细信息。
SIGSEGV 的 Valgrind 报告:
==28128== Memcheck, a memory error detector
==28128== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28128== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28128== Command: ./a.out
==28128== Parent PID: 27953
==28128==
==28128== Invalid read of size 8
==28128== at 0x400619: fun1 (tmp.c:18)
==28128== by 0x400695: fun (tmp.c:46)
==28128== by 0x4006A6: main (tmp.c:51)
==28128== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28128==
==28128==
==28128== Process terminating with default action of signal 11 (SIGSEGV)
==28128== Access not within mapped region at address 0x0
==28128== at 0x400619: fun1 (tmp.c:18)
==28128== by 0x400695: fun (tmp.c:46)
==28128== by 0x4006A6: main (tmp.c:51)
==28128== If you believe this happened as a result of a stack
==28128== overflow in your program's main thread (unlikely but
==28128== possible), you can try to increase the size of the
==28128== main thread stack using the --main-stacksize= flag.
==28128== The main thread stack size used in this run was 8388608.
==28128==
==28128== HEAP SUMMARY:
==28128== in use at exit: 0 bytes in 0 blocks
==28128== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated
==28128==
==28128== All heap blocks were freed -- no leaks are possible
==28128==
==28128== For counts of detected and suppressed errors, rerun with: -v
==28128== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
SIGBUS 的 Valgrind 报告:
==28176== Memcheck, a memory error detector
==28176== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28176== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28176== Command: ./a.out
==28176== Parent PID: 27953
==28176==
==28176==
==28176== HEAP SUMMARY:
==28176== in use at exit: 0 bytes in 0 blocks
==28176== total heap usage: 1 allocs, 1 frees, 5 bytes allocated
==28176==
==28176== All heap blocks were freed -- no leaks are possible
==28176==
==28176== For counts of detected and suppressed errors, rerun with: -v
==28176== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
违反了 C 标准的多个部分。
你 运行 与 6.3.2.3 Pointers, paragraph 7 有冲突:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
以及违反6.5 Expressions, paragraph 7的strict-aliasing规则:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
根据 the Valgrind documentation for Memcheck:
4.1. Overview
Memcheck is a memory error detector. It can detect the following
problems that are common in C and C++ programs.
Accessing memory you shouldn't, e.g. overrunning and underrunning heap blocks, overrunning the top of the stack, and accessing memory
after it has been freed.
Using undefined values, i.e. values that have not been initialised, or that have been derived from other undefined values.
Incorrect freeing of heap memory, such as double-freeing heap blocks, or mismatched use of malloc/new/new[] versus
free/delete/delete[]
Overlapping src and dst pointers in memcpy and related functions.
Passing a fishy (presumably negative) value to the size parameter of a memory allocation function.
Memory leaks.
注意你的代码
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
做 none Valgrind 声称检测的事情。您没有访问您无权访问的内存,也没有访问您使用 malloc()
创建的区域边界之外的内存。您还没有 free()
记忆。您没有未初始化的变量,您没有加倍 free()
内存,也没有对重叠的源区域和目标区域使用 memcpy()
不当。而且您没有将负数/"fishy" 大小传递给分配函数。而且你没有泄漏任何内存。
所以,不,Valgrind 甚至没有声称能够检测到会导致 SIGBUS
.
的代码
编辑 1:示例程序的平台是 x86_64。
编辑 2: 我正在编辑它以便更好地理解。下面是两个不同的问题。第一个问题是 invalid read/write 会导致 SIGBUS 吗?第二个问题是 Valgrind 对 SIGBUS 分析有用吗?。示例代码用于第二个问题以支持我的观点,即 Valgrind 在 SIGBUS 错误的情况下根本没有用。我这里可能是错的。
实际情况: 我们有一个屏幕 reader 应用程序在连续测试 2 天后崩溃(一次由于 SIGBUS 而崩溃)。我有一个 coredump 文件,但我没有正确的二进制和调试包。所以基本上我必须在不同的二进制文件中测试它,并且由于调试包不匹配,coredump 在 gdb 中无法正常工作。在 Valgrind 分析期间,我可以在 screen-reader 模块中看到一些无效的 read/write。我的队友建议通过修复这些无效的 read/write 将解决此问题,但我认为它不会解决它。以下是我对这两种信号的理解。
SIGSEGV: 地址有效但 read/write 权限不存在。
SIGBUS:地址本身无效(CPU由于对齐错误等原因无法找到地址)
我有一个关于 SIGBUS 信号的问题。我在堆栈溢出上搜索过类似的问题,但没有找到这个问题的明确答案。
无效read/write会导致总线错误(SIGBUS)吗?.
我的理解是,无效的 Read/Write 总是会导致分段错误 (SIGSEGV),修复总线错误的最佳方法是在应用程序上使用 运行 gdb。发生总线错误时的 Valgrind 分析根本没有帮助。下面的代码更详细地解释了这一点。
#include<stdlib.h>
#include<stdio.h>
typedef struct {
char *name;
int val;
}data;
void fun1()
{
data *ptr = malloc(sizeof(data));
ptr->val = 100;
ptr->name = "name in structure";
printf("val:%d name:%s\n",ptr->val,ptr->name);
free(ptr);
ptr = NULL;
printf("val:%d name:%s\n",ptr->val,ptr->name); //SIGSEGV
return;
}
int fun2()
{
#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__("pushf\norl [=11=]x40000,(%esp)\npopf");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("pushf\norl [=11=]x40000,(%rsp)\npopf");
# endif
#endif
char *cptr = malloc(sizeof(int) + 1);
char *optr = cptr;
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
free(optr);
return 0;
}
void fun()
{
fun2();
//fun1();
}
int main()
{
fun();
return 0;
}
在分段错误的情况下,Valgrind 报告将包含有关导致崩溃的代码的详细信息,但在 SIGBUS 崩溃的情况下,我在 Valgrind 报告中没有找到任何此类详细信息。
SIGSEGV 的 Valgrind 报告:
==28128== Memcheck, a memory error detector
==28128== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28128== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28128== Command: ./a.out
==28128== Parent PID: 27953
==28128==
==28128== Invalid read of size 8
==28128== at 0x400619: fun1 (tmp.c:18)
==28128== by 0x400695: fun (tmp.c:46)
==28128== by 0x4006A6: main (tmp.c:51)
==28128== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==28128==
==28128==
==28128== Process terminating with default action of signal 11 (SIGSEGV)
==28128== Access not within mapped region at address 0x0
==28128== at 0x400619: fun1 (tmp.c:18)
==28128== by 0x400695: fun (tmp.c:46)
==28128== by 0x4006A6: main (tmp.c:51)
==28128== If you believe this happened as a result of a stack
==28128== overflow in your program's main thread (unlikely but
==28128== possible), you can try to increase the size of the
==28128== main thread stack using the --main-stacksize= flag.
==28128== The main thread stack size used in this run was 8388608.
==28128==
==28128== HEAP SUMMARY:
==28128== in use at exit: 0 bytes in 0 blocks
==28128== total heap usage: 2 allocs, 2 frees, 1,040 bytes allocated
==28128==
==28128== All heap blocks were freed -- no leaks are possible
==28128==
==28128== For counts of detected and suppressed errors, rerun with: -v
==28128== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
SIGBUS 的 Valgrind 报告:
==28176== Memcheck, a memory error detector
==28176== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==28176== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==28176== Command: ./a.out
==28176== Parent PID: 27953
==28176==
==28176==
==28176== HEAP SUMMARY:
==28176== in use at exit: 0 bytes in 0 blocks
==28176== total heap usage: 1 allocs, 1 frees, 5 bytes allocated
==28176==
==28176== All heap blocks were freed -- no leaks are possible
==28176==
==28176== For counts of detected and suppressed errors, rerun with: -v
==28176== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
违反了 C 标准的多个部分。
你 运行 与 6.3.2.3 Pointers, paragraph 7 有冲突:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.
以及违反6.5 Expressions, paragraph 7的strict-aliasing规则:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
根据 the Valgrind documentation for Memcheck:
4.1. Overview
Memcheck is a memory error detector. It can detect the following problems that are common in C and C++ programs.
Accessing memory you shouldn't, e.g. overrunning and underrunning heap blocks, overrunning the top of the stack, and accessing memory after it has been freed.
Using undefined values, i.e. values that have not been initialised, or that have been derived from other undefined values.
Incorrect freeing of heap memory, such as double-freeing heap blocks, or mismatched use of malloc/new/new[] versus free/delete/delete[]
Overlapping src and dst pointers in memcpy and related functions.
Passing a fishy (presumably negative) value to the size parameter of a memory allocation function.
Memory leaks.
注意你的代码
int *iptr = (int *) ++cptr;
*iptr = 42; //SIGBUS
做 none Valgrind 声称检测的事情。您没有访问您无权访问的内存,也没有访问您使用 malloc()
创建的区域边界之外的内存。您还没有 free()
记忆。您没有未初始化的变量,您没有加倍 free()
内存,也没有对重叠的源区域和目标区域使用 memcpy()
不当。而且您没有将负数/"fishy" 大小传递给分配函数。而且你没有泄漏任何内存。
所以,不,Valgrind 甚至没有声称能够检测到会导致 SIGBUS
.