内存违规:SIGSEGV 和“找不到虚拟 table... 的链接器符号”

Memory violation: SIGSEGV and 'can't find linker symbol for virtual table...'

我在 C++ 代码中遇到内存冲突错误,这让我抓狂。我必须使用一些现有的 classes,它们几乎在其他任何地方都可以正常工作。

我正在尝试制作自定义数组对象的副本,而不是稍后修改内部值。但是那个复制操作有问题...

症状如下:

MyClass<T>与有问题的部分没有任何关系,经过搜索我发现这个错误可能是在vtable被覆盖(link)时出现的。

SIGSEGV 出现在此代码段的末尾:

// New boxes based on previous content, so first make a copy
Array<Box> nextBoxes(size);
int ic = followingItems.length();  // Array<int> followingItems() : some item id
for (int b = 0; b < size; ++b) {
    Box box(ic, capacity);
    const Box& oBox = currentBoxes[b];  // Array<Box> currentBoxes(size);
    for (int i = 0; i < ic; ++i) {
        if (oBox[i])
            box.add(i);
    }
    nextBoxes.add(box);
}

createConfig(nextBoxes, nextItems);
...
generateCostMatrix(nextBoxes, costMatrix); // <--[SIGSEGV] without any reason, variables are fine

这就是我完全迷失的地方。我尝试使用 std::vector 而不是 Array<Box> nextBoxes 但问题仍然存在,只是出现在不同的位置。

这是 'legacy' classes 中的一个:

class Box 
{
    Array<bool> items;  // mask of all tools
    int capacity, itemCount, count;
public:
    Box();
    Box(int num, int cap)
      : items(num), capacity(cap), itemCount(num), count(0)
    {
        for (int i = 0; i < num; i++)
            items.add(false);
    }
    Box(const Box& value){...}
    ~Box(){...}
    ...

来自崩溃位置的微小调试器信息:

array = new T[maxlen]
// values: array=0x0, maxlen=30, len=0 --> looks OK

(在 Array<T> class 的某个深处,在哪里并不重要,因为总是像这里一样在 new 行中发生,并且总是没有明显的原因)

好吧,有件事没有引起我的注意... 过度索引数组主要发生在索引超出范围时。有时数组太短,或者索引太长,或者您创建了错误大小的数组。而最后一个案例就发生在这里。

我之所以回答这个问题是因为:

我已经看到引用的警告消息,但在完全不同的情况下(真正的链接问题,当节点实际上从 vtable 中丢失时)。在我的例子中,由于一些错误的数组处理,虚拟 table 被覆盖,令人惊讶。

Just for the future googlers, this can useful to debug a SIGSEGV which appears at a weird location.

我学到了什么:

  • 始终仔细检查容器对象(不仅仅是索引变量)

  • 三重检查 提出新问题时引用的来源(是的,该问题在关键行中包含错字)


这里是解决方案,不是那么重要,但为了完整性...

ic 的值是 'bad guy',需要深入我的项目才能发现它,但我会解释它:

int ic = followingItems.length(); // where Arra<int> followingItems(x);

followingItems是项目ids(Arra<int>的列表) 需要插入。 x 可以在 [1, allItemCount]

范围内

Box class中,Array<bool> items是一个布尔掩码,用于标记一个项目是否在盒子里。显然,items.length() = allItemCount 所以:

followingItems.length <= allItemCount

首先,我意识到 ic87 之前是 运行 而不是 400。我想复制全部内容,但只测试并添加了前 87 项。 考虑到这一点,我发现了主要错误:

Box box(ic, capacity);

第一个参数应该是所有项目的数量,但又是 87 而不是 400。好吧,这很痛苦...