内存违规:SIGSEGV 和“找不到虚拟表的链接器符号...”
Posted
技术标签:
【中文标题】内存违规:SIGSEGV 和“找不到虚拟表的链接器符号...”【英文标题】:Memory violation: SIGSEGV and 'can't find linker symbol for virtual table...' 【发布时间】:2015-11-05 12:06:44 【问题描述】:我在 C++ 代码中遇到内存冲突错误,这让我抓狂。我必须使用一些现有的类,它们几乎在其他任何地方都能正常工作。
我正在尝试制作自定义 Array 对象的副本,而不是稍后修改内部值。但是那个复制操作有问题……
症状如下:
Segmentation fault
复制后,但不是立即
警告:can't find linker symbol for virtual table for 'MyClass<T>' value
MyClass<T>
与问题部分无关,搜索后发现vtable被覆盖(link)时可能会出现此错误。
SIGSEGV 出现在这个 sn-p 的末尾:
// 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
,但问题仍然存在,只是出现在不同的位置。
这是“遗留”类中的一个:
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>
类的深处,在哪里并不重要,因为总是像这里一样发生在 new
行中,而且总是没有明显的原因)
【问题讨论】:
首先在调试器中运行以捕获崩溃,然后在代码中找到崩溃发生的位置并检查所有相关变量的值。如果您仍然无法弄清楚,那么至少告诉我们崩溃发生的位置和变量值。 在 Array 模板类中 add 有什么作用 我用崩溃位置和add()
的定义扩展了这个问题。希望你能看到我看不到的东西。
memset(array, 0, maxLen * sizeof(T));
是一个错误,你应该改用默认初始化。
您可能会覆盖数组边界和/或在某处使用悬空引用。此类问题应包括MCVE。从错误的代码开始向后工作,一次删除大部分,直到您拥有仍然存在问题的最小程序。
【参考方案1】:
嗯,有些事情没有引起我的注意... 过度索引数组主要发生在索引超出范围时。有时数组太短,或者索引太长,或者你创建了错误大小的数组。最后一个案例发生在这里。
我回答这个问题的原因是:
我看到了引用的警告消息,但在完全不同的情况下(真正的链接问题,当 vtable 中实际上缺少一个节点时)。在我的情况下,虚拟表被覆盖,令人惊讶的是,由于一些糟糕的数组处理。
对于未来的谷歌人来说,这对于调试 SIGSEGV 很有用 出现在一个奇怪的位置。
我学到了什么:
总是仔细检查容器对象(不仅仅是索引变量)
三重检查您提出新问题时引用的来源(是的,该问题的关键行中有错字)
这里是解决方案,不是那么重要,但为了完整性......
ic
的价值是“坏人”,需要深入我的项目才能发现它,但我会解释一下:
int ic = followingItems.length(); // where Arra<int> followingItems(x);
followingItems
是需要插入的ids(Arra<
int>
)项的列表。
x
可以在[1, allItemCount]
范围内
在Box
类中,Array<bool> items
是一个布尔掩码,用于标记项目是否在框中。不知不觉,items.length() = allItemCount
所以:
followingItems.length <= allItemCount
首先,我意识到ic
一直运行到87
而不是400
。我想复制全部内容,但只测试并添加了前 87 项。
考虑到这一点,我发现了主要错误:
Box box(ic, capacity);
第一个参数应该是所有项目的数量,但又是 87 而不是 400。好吧,那是相当痛苦的......
【讨论】:
以上是关于内存违规:SIGSEGV 和“找不到虚拟表的链接器符号...”的主要内容,如果未能解决你的问题,请参考以下文章