gpt4 book ai didi

无效的读/写会导致 SIGBUS 错误吗?

转载 作者:太空宇宙 更新时间:2023-11-04 02:21:47 27 4
gpt4 key购买 nike

编辑 1:示例程序的平台是 x86_64。

编辑 2: 我正在编辑它以便更好地理解。下面是两个不同的问题。第一个问题是无效的读/写会导致 SIGBUS 吗?第二个问题是 Valgrind 对 SIGBUS 分析有用吗?。示例代码用于第二个问题以支持我的观点,即 Valgrind 在 SIGBUS 错误的情况下根本没有用。我在这里可能是错的。

实际情况:我们有一个屏幕阅读器应用程序,它在连续测试 2 天后崩溃(一次崩溃是由于 SIGBUS)。我有一个 coredump 文件,但我没有正确的二进制和调试包。所以基本上我必须在不同的二进制文件中测试它,并且由于调试包不匹配,coredump 在 gdb 中无法正常工作。在 Valgrind 分析期间,我可以在屏幕阅读器模块中看到一些无效的读/写。我的队友建议通过修复这些无效的读/写将解决这个问题,但我认为它不会解决它。以下是我对这两种信号的理解。

SIGSEGV:地址有效但没有读/写权限。

SIGBUS:地址本身无效(由于对齐错误等原因,CPU 无法找到地址)

我有一个与 SIGBUS 信号相关的问题。我在堆栈溢出上搜索了类似的问题,但没有找到这个问题的任何明确答案。

无效读/写会导致总线错误(SIGBUS)吗?

我的理解是无效读/写总是会导致段错误 (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 $0x40000,(%esp)\npopf");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("pushf\norl $0x40000,(%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 的严格别名规则:

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

不执行 Valgrind 声称检测到的任何事情。您不会访问您无权访问的内存,也不会访问您使用 malloc() 创建的区域边界之外的内存。您还没有free() 释放内存。您没有未初始化的变量,您没有双倍 free() 内存,也没有对重叠的源区域和目标区域不正确地使用 memcpy()。而且您不会将负数/“可疑”大小传递给分配函数。而且您没有泄漏任何内存。

所以,不,Valgrind 甚至没有声称能够检测到会导致 SIGBUS 的代码。

关于无效的读/写会导致 SIGBUS 错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56758924/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com