这可能有什么问题吗?

发布于 2024-08-14 11:29:13 字数 2392 浏览 3 评论 0原文

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


当我在家构建程序时,它工作正常,但是当我使用大学系统时,我的系统就会崩溃。当我使用 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

有什么想法要开始寻找吗?


顺便说一句:我仅使用如下语句填充列表: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),所以我在学校系统上运行了我在家编译的二进制文件,并且运行良好。

BTW: I found the problem: (See my answer below)


When I build my program at home it works fine, but when I use my universities system is crashing on me. When I go at it with GDB I get this:

(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

It crashes from a SEG-V on a line with a virtual function call involving 2 variable and neither is NULL. I don't think there is anywhere else that stuff from this list is deleted.

Tossing it a Valgrind gives one error:

==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

Any idea were to start looking?


BTW: I populate the list using only statements like this: 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;


Yet more: It happens that the home and school systems are both x86 (RHEL 3 and 5 respectively) so I ran the binary I compiled at home on the system at school and it runs fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

兰花执着 2024-08-21 11:29:13

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

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

The value of the pointer is probably the victim of a wild write from somewhere else.

The variable p shown in your debugger output is 0x2064696c. That is probably the string "lid ", depending on your byte ordering. You should look for somewhere in your code where that string (or value) was stored.

花辞树 2024-08-21 11:29:13

列表中的指针之一无效。这可能是因为它是 null (不是您的情况)、未初始化、通过错误的强制转换初始化或它曾经指向的有效对象已被销毁。

因为它在一种环境中有效,但在另一种环境中无效,因此您可能会看到一些未定义行为的结果。

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

One of the pointers in your list is invalid. This could be because it is null (not in your case), uninitialized, initialized via a bad cast or the valid object that it once pointed to has been destroyed.

Because it works in one environment and not in another you are probably seeing the results of some undefined behaviour.

When you push the pointers onto the list, what objects are they pointing to and what happens to those objects at the time you call Finish?

梨涡少年 2024-08-21 11:29:13

您将第 44 行上的 p 取消引用到一个不存在的对象。

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

编辑:我建议开始查看此列表的填充位置,并验证您的列表项是否已初始化为 0,并且您实际上将指针分配给了 实例修补到列表。此外,您还可能会查找在初始化过程中忽略或捕获的其他错误或异常,这些错误或异常允许像这样指向无效内存的指针将其放入列表中。

You're dereferencing p on line 44 to an object that doesn't exist.

Either p was never initialized, or *p has already been deleted.

Edit: I'd recommend to start looking where this list is populated, and verify that your list items are initialized to 0, and that you actually assign pointers to your Patch instances to the list. Also you might look for other errors or exceptions that you're ignoring or catching during the initialization process that are allowing pointers to invalid memory like this to make it into the list.

勿忘初心 2024-08-21 11:29:13

我是如何发现这个问题的。

首先向janm 用于识别出了什么问题,即使它对于查找问题所在没有多大帮助。


我添加了一个测试函数,它实际上是失败函数的副本,但消除了所有副作用。通过它在整个地方运行,我能够将事情分解到一个小窗口中。在调试器下,我从最后一个有效传递单步执行到第一个无效传递,并得到以下结果:

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 的引用将是一件好事。

How I found the problem.

First a tip of the hat to janm for identifying what was going wrong even if it didn't help much in finding where.


I added a Test function that is effectively a copy of the function that fails, but with all the side effects stripped out. With it running all over the place I was able to isolate where things break down into a small windows. Under the debugger, I single stepped from that last valid pass to the first invalid pass and got this:

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();

Formatted for clarity, the memory corruption must be caused by one of these lines:

-- 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";

Because that not to long a list, I just added even more logging till I found that these line causes the problem:

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

Now that I know exactl where to look it easy to see the problem, and by switching to:

++at;
if(at != ops.end()) (*at).head = c;

the problem goes away.


The only questions I still have are 1) why did it work at all on my old system? and 2) why didn't that manifest as a seg-v right on the second line? I would think that having *(list.end()) result in a reference to NULL would be a good thing.

隱形的亼 2024-08-21 11:29:13

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

当您使用 ++ 增加指针时,它会增加它所指向的内容的大小。由于您使用的是 !=,因此您可能没有准确地命中 Patchups.end(),因此您会走开,然后进入无效内存。

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

You should use < in your conditional statement.

When you increment a pointer using ++, it increases it by the size of whatever it points to. Since you're using !=, it's possible that you're not hitting Patchups.end() exactly, and so you're walking off then end into invalid memory.

Or it might be something else. There might be invalid memory somewhere between begin() and end(), for example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文