【问题标题】:C++ Copy through assignment problemC++ Copy through assignment问题
【发布时间】:2010-07-22 13:32:20
【问题描述】:

我似乎在使用以下功能时遇到了问题:

void OtherClass::copy_this( int index, MyClass &class_obj)
{
    if(index < MAX_index)
        class_obj = array_of_MyClass[index];
}

OtherClass 维护着一个 MyClass 对象数组,我希望这个函数将选定的对象从数组中复制到提供的 class_obj 中。

当我运行时,程序到达此函数时出现分段错误。在 gdb 中运行它并查看回溯会发现,当它到达赋值行时,执行会向后跳近 100 行,进入一个完全不同的函数的中间。它跳转到的行是:

temp_obj = array_of_MyClass[other_index]

gdb 回溯的相关输出是:

#0  0x0000003c7ae7256c in memcpy () from /lib64/tls/libc.so.6
#1  0x000000000043264e in MyClass::operator= (this=0x4c0000004c, _ctor_arg=@0x7fbffd8228) at ../location.cpp:156
#2  0x0000000000432569 in OtherClass::copy_this (this=0x7fbffd8220, index=0, section=@0x4c0000004c) at ../location.cpp:254

明明是同一类型的操作,但到底为什么执行会这样呢?我在程序中的任何地方都没有 longjumps、gotos 等。我也没有用户定义的赋值运算符、复制构造函数等,所以回溯中的“operator=”令人费解。

在有人问之前,不,我不能发布整个代码。 (对不起!)我意识到这可能无法确定我的问题;如果是这种情况,请告诉我。

提前致谢!


在再次运行它并测试了几个“最简单的用例”之后,似乎问题实际上是在执行的早期某个地方引入的,所以它又回到了我的绘图板上。谢谢大家的帮助!

【问题讨论】:

  • 您是否创建了自己的复制构造函数和/或赋值运算符?您是否在启用优化的情况下进行编译(即 g++ -O3)?
  • 你是怎么传入数组array_of_MyClass的?
  • 更多信息...!是否有任何相关的编译器警告?有什么奇怪的演员表吗? temp_obj 是参考还是本地? -Wall 怎么样?我问是因为奇怪似乎试图使用无效的参考
  • 不,我没有。我正在编译: g++ -O0 -g3 -Wall -c -fmessage-length=0 pkg-config gtkmm-2.4 --cflags --libs 这是一个 Eclipse 管理的 make 项目,如果这很重要的话。

标签: c++ copy segmentation-fault variable-assignment


【解决方案1】:

索引是否有效?我看到您与 MAX_index 进行比较,但是您的数组是否包含 MAX_index、已初始化的元素?我问是因为,如果你复制一个无效的对象,你就会像你描述的那样有未定义的(不愉快的)行为。

另一种可能性(如果不是这个)是进行全面重建的时候了。调试信息已损坏,或者生成的代码不完整(由于构建过程中的任何原因)。

【讨论】:

  • 好吧,这发生在索引为零的情况下,我知道在调用此函数之前数组 [0] 中有一个对象。 MAX_index 和array_of_MyClass 实际上都是OtherClass 的类对象。 MAX_index 是随着对象被添加到数组中而递增的计数器。我尝试了完全重建,但没有效果。 (可悲。)
【解决方案2】:

代码是否使用优化器标志编译?优化器可以对执行流程做一些非常奇怪的事情,包括从一个函数跳转到一个完全不相关的函数,而该函数恰好有一段代码可以完成第一个函数需要的操作。

【讨论】:

    【解决方案3】:

    您说执行向后跳转的那一行是对 MyClass 类对象的赋值。这就是您在回溯中看到MyClass::operator= 的原因。 您说您没有用户定义的赋值运算符或复制构造函数,因此这将在回溯中解释其正上方的 memcpy(),因为这是复制的默认实现(浅复制)。

    在这种情况下,我认为实现一个复制构造函数(对于 Myclass)可能会有所帮助。

    关于段错误本身 - 数组是如何初始化的?数组的索引 0 中有什么? (好像在通话中使用过)

    【讨论】:

    • 这是有道理的。我认为默认运算符会很好,因为我只需要一个浅拷贝。至于段错误,请参阅我对 Catalin 的回答。
    【解决方案4】:

    您没有它们,但编译器无论如何都会生成它们,这就是您在使用 = 运算符时所调用的。最有可能的是默认赋值运算符对于 MyClass 来说是不够的,这就是它不起作用的原因。明确实施它们,看看这是否解决了问题。

    没有更多的源代码,没有什么可以推荐的。

    【讨论】:

    • 可以理解。我认为这可能是默认赋值运算符的问题。我会尝试一个显式的实现,看看是否有帮助。
    【解决方案5】:

    应该多关注几帧回来,我就会看到答案了。

    我试图将数据复制到其中的 MyClass 对象已初始化为 NULL 指针,这是 memcpy() 中的错误的来源。 (“无法访问地址 0x0 处的内存”——天哪!)不敢相信我错过了...

    感谢您的帮助 - 如果我没有尝试过您的解决方案,我可能会继续用头撞墙。明确编写赋值运算符使我确信问题出在其他地方。

    谢谢你!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 1970-01-01
      • 2015-04-20
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多