当我在家里制作我的节目时,它工作得很好,但是当我使用我的大学时,系统会让我崩溃。当我使用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)所以我在学校系统上运行了我在家编译的二进制文件,它运行正常。
答案 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()之间可能存在无效内存。