【问题标题】:Segfault Cannot access memory at addressSegfault 无法访问地址处的内存
【发布时间】:2013-02-18 15:17:26
【问题描述】:

我在下面的代码部分遇到了分段错误:(关于这个分段错误,我在一个主题中提出 2 个问题)

req_cw(ECM_REQUEST *er, int32_t flag, int32_t reader_types){

    LL_NODE *ptr;
    for (ptr = er->matching_rdr->initial ; ptr ; ptr = ptr->nxt) {
        if (ptr == er->fail)
            break;
    rdr = (struct s_reader*)ptr->obj;
    we_equest(rdr->fd, er);
    }
}

如您所见,即使使用带有if(ptr->obj && ptr) 的控制结构,也可以确保ptr(或ptr->obj 不会是null 指针)但它并不能阻止它,并且在我尝试分段错误之后打印值ptr->obj

打印 ptr->obj ,gdb 说:

(gdb) print ptr $1 = (LL_NODE *) 0x149

(gdb) x 0x149

0x149:无法访问地址 0x149 处的内存

我的问题是:如何防止这种分段错误,为什么会发生这种分段错误以及如何解决?

  1. 关于这个段错误,当使用 gdb 时,我检查了第 1 帧(发生段错误之前的一帧),我发现

er->cw 是"\000 <repeats 15 times>" 我的问题是如果er->cw 不等于"'\000' <repeats 15 times",我该如何控制?

我这样做了,我知道这是不正确的(我错过了一些东西),这就是我在这里问的原因

if (er->cw)
req_cw(er , ...)

问题在于添加if(er->cw)。我认为 cw 是字符,我不应该表现得像 integer ,但我不知道如何检查它是否不为零?我的意思是,即使当我检查 gdb 时再次使用这一行,仍然 er->cw "'\000'" 的值正在传递,那么如何使用 if 控制块检查 er->cw 何时不等于 '\000'"?

提前致谢。

【问题讨论】:

  • 0x149 绝对是一个无效的指针...问题出在您没有向我们展示的代码的另一部分
  • @Karoly ,我如何使用 gdb 找出 ox149 为什么无效,我的意思是如何使用 gdb 我可以检查你提到的无效指针?顺便说一句,我的第二部分问题是关于如何使用 if 函数检查 cw 是否不等于“'\000' 重复 15 次”?顺便说一句,既然你说问题出在代码的另一部分,你的意思是什么? (如果你说函数名,我也会提供那个源代码。谢谢
  • @All 至少我的第二部分问题对这个论坛的许多人来说都很简单!不是,所以在 50 次审查之后,没有回复第二部分,所以如果我用 if(strlen(er->cw) != 0) 检查这个控件是否对 er->cw 有效,以防止值为 '\ 000 重复 15 次?

标签: c segmentation-fault controls


【解决方案1】:

如您所见,即使使用带有 if(ptr->obj || ptr) 的控制结构来确保 ptr(或 ptr->null 不会是空指针)

问题是您进行测试的顺序,编译时首先完成ptr->obj,因此如果ptr 为空,则您正在访问无效内存获取obj 成员。 颠倒测试顺序if (ptr || ptr->obj)

但是这仍然不对...您的OR 逻辑也是错误的,代码应该是...

if ((ptr != NULL) && (ptr->obj != NULL))
{
   // use the pointer
}

【讨论】:

  • 嗯,不,不是这种情况,在版主编辑后会发生这种情况(你在第一篇文章中发现了一个错字),在我检查过的代码中 if (!ptr && !ptr-> obj) 这与你所说的完全一样,嗯,好的,我将我的问题限制在一个部分,如果我想检查 er->cw 这是数组的字符(数组的长度是 15),元素不会是零,我该怎么办? strlen (er->cw) != '\000' 能完成这项工作吗?
  • 这取决于 er->cw 的用途......如果它是一个文本字符串,那么检查 if (er->cw[0] == '\0') empty_string 就足以测试一个空字符串。测试if (er->cw=="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0") 是个坏主意。
  • 感谢 Anonymouse,检查 if (er->cw[0] == '\0' or '\000' 有什么区别吗?
  • 绝对的纯粹主义者会说是有区别的,\0 是 NULL 终止符,而 \000 是 ascii 字符 0。但实际上它们是相同的。
【解决方案2】:

As you see, even with the control structure with if(ptr->obj || ptr) to be sure ptr (or ptr->null won't be null pointer)

不...实际上并不能确保两者都不会为 NULL,这会使您陷入段错误。 || 将在退出之前评估 both 双方,并且无论如何您都可以向后设置逻辑。你想要&&,你需要翻转它们,否则它会尊重NULL指针:

if(ptr && ptr->obj)

当我尝试打印值 ptr->obj 时出现分段错误后:
print ptr->obj ,gdb 说:
...
0x149: 无法访问地址 0x149 的内存

我从未见过0x149 有效的地址,你在什么硬件平台上?


er->cw 是 "\000 " 我的问题是我如何控制 er->cw 不等于 "'\000'

不清楚,你能显示er 的结构吗?你是说er->cwchar * 类型并且设置为"\000 <repeats 15 times>"

【讨论】:

  • 感谢回复,cw是uchar cw[16]; (unsigned char) 硬件是 SH4 / stlinux
  • 注意 if(ptr && ptr->obj) 我知道,我说这是版主编辑造成的错字!
  • @nimatajfar 是的,并且您还说(在另一条评论中)您尝试了(!ptr && !ptr->obj),这是不正确的。我看到或编辑你的意思是没有!s。 SH4 是 32 位硬件,为什么不尝试使用 32 位地址访问地址呢?如果这是您的意图,C 将不知道用哪种方式填充它。由于cw 是一个字符数组,因此您需要逐个字符或与 str 函数进行比较,初始的\000 是一个转义字符,您应该看到cw[0] == 0
猜你喜欢
  • 2018-09-08
  • 1970-01-01
  • 2013-10-30
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多