【问题标题】:Segmentation Fault For Struct When All Values Are Non-Null当所有值都为非空时结构的分段错误
【发布时间】:2014-10-12 18:09:05
【问题描述】:
char *s = sbrk(some_num); 
if (s != (char *)-1) {    
  some_struct = (SomeStruct *)s;
  some_struct->num = 8; //num is an int [*SEG FAULT OCCURS ON THIS LINE*]
}

使用 gdb 调试:

p some_struct  => (SomeStruct *) 0xef7100
p some_struct->num  => 0

从之前的 q/a 中,我了解到当某些内容为 NULL 时会发生 seg 错误,但在此示例中,some_struct、some_struct->num 和 8 都是 non-NULL。。 p>

为什么会出现分段错误?如何将 some_struct->num 设置为某个 int 值?

【问题讨论】:

  • Seg 错误不仅在指针为 NULL 的情况下,还在于您对内存的访问错误。
  • 请发布可以在实践中验证的最少量代码。
  • 要么 0xef7100 不是有效指针,要么 num 是 *int 而不是 int
  • 更新问题,提供更多细节
  • 错误的内存访问/不是一个有效的指针 --- 谢谢,我会试着调查一下

标签: c


【解决方案1】:

指针 some_struct 需要指向一些有效内存。如果函数 some_function 返回指向某个局部 volatile 变量的指针,则该变量将在 some_function 退出时丢失。

为了避免段错误,您可以将 some_function 中的局部变量声明为静态,或者您可以通过让 some_function 调用 malloc 从堆中分配内存。如果 some_function 使用 malloc 分配内存,则调用者将负责确保稍后释放内存。

避免段错误的另一种方法是不返回指向局部变量的指针,而是返回全局变量。但是,大多数人都同意应该避免使用全局变量。

【讨论】:

  • 谢谢,这很有帮助!由于评论者的要求,我现在添加了更多细节:some_function --> sbrk(some_num)
  • 如果您没有为整个结构分配足够的内存,则在写入分配内存之外的结构部分时可能会出现段错误。
  • 另外,使用 malloc 代替 sbrk 来分配内存被认为更便携。
【解决方案2】:

熟悉虚拟内存的概念是值得的,它是当今大多数现代操作系统的基础。

在具有虚拟内存的操作系统下,每个内存地址(实际上是虚拟地址)都类似于电话号码,因为您不能以大约 10 位数字的每个组合来呼叫某人。

您只能拨打电话簿中列出的号码。

否则您会听到“抱歉,此号码目前无法使用”。

同样,只有在每个进程的“页表”中列出的那些虚拟地址(总是由操作系统自动透明地维护)才对进程的访问有效。

SEGV 是操作系统表示“抱歉,此虚拟地址当前无法使用”的方式。

malloc(和sbrk)基本上可以要求操作系统为你分配一个指定大小的内存块,并将其地址注册到页表中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 2021-02-19
    • 1970-01-01
    相关资源
    最近更新 更多