这可能有什么问题?

时间:2009-12-13 01:28:24

标签: c++ debugging stl segmentation-fault

顺便说一句:我发现了问题:(见下面的答案)


当我在家里制作我的节目时,它工作得很好,但是当我使用我的大学时,系统会让我崩溃。当我使用GDB时,我得到了这个:

(gdb) r t.c-
Starting program: /home/shro8822/p5/c- t.c-
*--Code Gen Function: main
*--in function 'main' variable offsets start at 2

Program received signal SIGSEGV, Segmentation fault.
0x08084410 in ObjectCode::ResolveRef (this=0xbfb3dd20) at CodeOutput.cpp:44
44                      p->Resolve(this);
(gdb) list
39      {
40              std::list<Patch*>::iterator pos;
41              for(pos = Patchups.begin(); pos != Patchups.end(); ++pos)
42              {
43                      Patch* p = *pos;
44                      p->Resolve(this);
45                      //delete p;
46              }
47
48      }
(gdb) p p
$1 = (class ObjectCode::Patch *) 0x2064696c
(gdb) p this
$2 = (ObjectCode * const) 0xbfb3dd20

它在一行上的SEG-V崩溃,虚拟函数调用涉及2个变量,两者都不是NULL。我不认为此列表中的内容会被删除。

将它扔给Valgrind会出现一个错误:

==5714== Invalid read of size 4
==5714==    at 0x8084410: ObjectCode::ResolveRef() (CodeOutput.cpp:44)
==5714==    by 0x8086E00: ObjectCode::Finish() (CodeOutput.cpp:196)
==5714==    by 0x807EC97: WalkGlobal::Finish() (CodeGen_G.cpp:211)
==5714==    by 0x808D53C: Compile::RunV() (cs445.cpp:120)
==5714==    by 0x808D7C2: ProcessFile::Run() (cs445.cpp:49)
==5714==    by 0x808CCD9: main (cs445.cpp:234)
==5714==  Address 0x2064696C is not stack'd, malloc'd or (recently) free'd
Seg fault

任何想法都要开始寻找?


BTW:我只使用这样的语句填充列表:Patchups.push_back(new PatchType());

shro8822 p5 $ grep Patchups *.cpp *.h -n
CodeOutput.cpp:41:      for(pos = Patchups.begin(); pos != Patchups.end(); ++pos)
CodeOutput_Slot.cpp:124:        { Stream->Patchups.push_back(new FunctionPatch(it,GetSlotBefor(),at)); }
CodeOutput_Slot.cpp:126:        { Stream->Patchups.push_back(new GotoPatch(target,GetSlotBefor(),at,"goto")); }
CodeOutput_Slot.cpp:128:        { Stream->Patchups.push_back(new GotoPatch(target,GetSlotBefor(),at,c)); }
CodeOutput_Slot.cpp:130:        { Stream->Patchups.push_back(new BranchPatch(target,GetSlotBefor(),type,from,at,c)); }
CodeOutput.h:222:       std::list Patchups;


更多:碰巧家庭和学校系统都是x86(分别是RHEL 3和5)所以我在学校系统上运行了我在家编译的二进制文件,它运行正常。

5 个答案:

答案 0 :(得分:2)

指针的值可能是来自其他地方的疯狂写入的受害者。

调试器输出中显示的变量p为0x2064696c。这可能是字符串“lid”,具体取决于您的字节顺序。您应该在代码中找到存储该字符串(或值)的位置。

答案 1 :(得分:1)

列表中的一个指针无效。这可能是因为它是null(不是你的情况),未初始化,通过坏的转换初始化或它曾经指向的有效对象已经被破坏。

因为它可以在一个环境中而不是在另一个环境中工作,所以您可能会看到某些未定义行为的结果

当你将指针推到列表上时,它们指向哪些对象以及在调用Finish时这些对象会发生什么?

答案 2 :(得分:0)

您将第44行的p解除引用到不存在的对象。

p从未初始化,或*p已被删除。

修改:我建议您开始查看此列表的填充位置,并验证列表项是否已初始化为0,并确实指定了指向{{1}的指针1}}实例到Patch。此外,您可能会在初始化过程中查找您忽略或捕获的其他错误或异常,这些错误或异常允许指向无效内存的指针,以使其进入list

答案 3 :(得分:0)

我是如何发现问题的。

首先向janm提示,以确定哪些内容出了问题,即使它在找到哪里方面没什么帮助。


我添加了一个Test函数,它实际上是失败函数的副本,但是所有副作用都被删除了。随着它在各处运行,我能够将事物分解成一个小窗口。在调试器下,我单从最后一次有效传递步进到第一个无效传递,得到了这个:

CodeOutput.cpp:224  |  ObjectCode::Test();
CodeOutput.cpp:225  |  continue;
CodeOutput.cpp:111  |  while(at != ops.end())
stl_list.h:598      |  { return iterator(&this->_M_impl._M_node); }
stl_list.h:127      |  : _M_node(__x) { }
stl_list.h:174      |  { return _M_node != __x._M_node; }
CodeOutput.cpp:113  |  printf("%s\n", (*at).TypeStr());
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
CodeOutput_asm.cpp:33   |  switch(Type)
CodeOutput_asm.cpp:36   |  Case(OpPlaceholder);
CodeOutput.cpp:115  |  switch((*at).Type)
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:216  |  char* c = (*at).comment;
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:217  |  if((*at).head != NULL && (*at).head[0] != '\0')
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:222  |  ++at;// = ops.erase(at);
stl_list.h:141      |  _M_node = _M_node->_M_next;
stl_list.h:142      |  return *this;
CodeOutput.cpp:223  |  (*at).head = c;
stl_list.h:132      |  { return static_cast(_M_node)->_M_data; }
CodeOutput.cpp:224  |  ObjectCode::Test();

为清晰起见,格式化内存损坏必须由以下行之一引起:

-- last valid test
CodeOutput.cpp:224  |  ObjectCode::Test();

CodeOutput.cpp:225  |  continue;

-- falls into loop ('at' is list::iterator)
CodeOutput.cpp:111  |  while(at != ops.end()) 
CodeOutput.cpp:113  |  printf("%s\n", (*at).TypeStr());
CodeOutput.cpp:115  |  switch((*at).Type)

-- OpPlaceholder case
CodeOutput.cpp:216  |  char* c = (*at).comment;

-- if gets false ('head' is char*)
CodeOutput.cpp:217  |  if((*at).head != NULL && (*at).head[0] != '\0')
CodeOutput.cpp:222  |  ++at;
CodeOutput.cpp:223  |  (*at).head = c;

-- first invalid test
CodeOutput.cpp:224  |  ObjectCode::Test();

-- called from CodeOutput.cpp:113
CodeOutput_asm.cpp:33   |  switch(Type)
CodeOutput_asm.cpp:36   |  case  OpPlaceholder; return "OpPlaceholder";

因为不长的列表,我只是添加了更多的日志记录,直到我发现这些行导致了问题:

++at;
(*at).head = c;

现在,我知道在哪里可以轻松查看问题,并切换到:

++at;
if(at != ops.end()) (*at).head = c;
问题消失了。


我还有的唯一问题是1)为什么它在我的旧系统上完全有效? 2)为什么没有在第二行显示为seg-v?我认为让*(list.end())导致对NULL的引用会是一件好事。

答案 4 :(得分:-3)

您应该在条件语句中使用<

使用++增加指针时,它会增加指向它的大小。因为你正在使用!=,你可能没有准确地击中Patchups.end(),所以你走了然后结束了无效的记忆。

或者它可能是别的东西。例如,在begin()和end()之间可能存在无效内存。