class SimpleVariant
{
public:
SimpleVariant() { /*...*/ };
// ...
};
struct VariantBlock
{
int nRows, nCols;
vector<SimpleVariant> theData;
};
void dumbFunction( VariantBlock& theBlock, int nRows, int nCols )
{
// ...
cout << "theBlock.nRows= " << theBlock.nRows
<< ", theBlock.nCols= " << theBlock.nCols
<< ", theBlock.theData.size() " << theBlock.theData.size();
theBlock.theData.resize( nRows * nCols );
// throws Access Violation Exception
// ...
}
输出返回nRows = 61,nCols = 5,size()= 0,这正是在抛出访问冲突异常之前的那一点。
我正在使用MSVC6,这显然不是最佳选择,但此时别无选择。
答案 0 :(得分:2)
我最近不得不升级一些最初为Visual C ++ 6编写的代码。该代码有问题,因为VC ++ 6没有处理可以正确绑定到引用的内容。这是在黑暗中拍摄的东西,但是你是否正在const VariantBlock
传递给dumbFunction
?在C ++规则下,这是非法的,但我强烈怀疑VC ++ 6会出错。
另一种可能性是某种运行时不匹配。如果(1)VariantBlock
分配在一个模块中,(2)dumbFunction
来自不同的模块,和(3)它们是使用不同的设置编译的,可能是不同的编译器的版本,然后您将看到这种行为(resize()
分配新内存,将所有内容复制到它,然后去释放旧内存,除了旧内存分配在不同的运行时,所以程序barfs)。
简而言之,您发布的代码完全没问题。还有其他事情要发生。
答案 1 :(得分:1)
我认为你在错误之前做错了什么。 std::vector::resize
操作将要求内存,堆很容易成为腐败的受害者。关于未定义行为的坏处是,在错误发生后,症状可以看到一百万个执行指令(即“任何事情都可能发生”包括“无”)。
我们有一个“调试内存管理器”,它重新定义了全局分配器,并且可以对腐败进行大量检查:
__FILE__/__LINE__
信息标记每个块,以检测是谁泄漏了内存泄漏,并能够告诉谁正在使用删除后损坏的块。我们还有一个内存检查例程,按需可以遍历所有内存块并检查一致性(通常我们只检查分配/解除分配)。我们还可以为绝望案例注销所有内存分配/解除分配的完整列表。
不幸的是,对于第(5)点,C ++语法难以检测,因此我们实际上不使用new
而是使用最终扩展为放置分配的xnew
宏;这也意味着我们无法检测标准库中分配的内存块(我们存储了在库中分配之前在程序中进行分配的最后一行源代码)。
答案 2 :(得分:1)
我是OP。
问题是来自调用函数的内存损坏。