2011-03-26 45 views
-1
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,这正是它应该在那一点上,在引发访问冲突异常之前。Soul-crushing C++ std :: vector :: resize()访问冲突错误

我正在使用MSVC6,这显然不是最佳的,但在这一点上没有选择。

+0

你在'SimpleVariant'中有什么类型的成员?你是否为'SimpleVariant'声明了复制构造函数和/或复制赋值运算符?如果是这样,他们做什么?您发布的代码没有任何明显的错误,尽管我最近没有使用VC6的经验。 – 2011-03-26 05:18:21

+0

我没有定义它们。 – Doug 2011-03-26 05:19:36

+2

这可能是坏的复制行为,正如詹姆斯指出的那样,但它也可能是程序中其他地方的内存破坏。 – templatetypedef 2011-03-26 05:20:46

回答

2

我最近不得不升级一些最初为Visual C++ 6编写的代码。该代码有问题,因为VC++ 6没有处理可以正确绑定到引用的东西。这是在黑暗中拍摄的东西,但你是否传递const VariantBlockdumbFunction?在C++规则下,这将是非法的,但我强烈怀疑VC++ 6会出错。

另一种可能性是某种运行时不匹配。如果(1)VariantBlock分配在一个模块中,并且(2)dumbFunction来自不同的模块,则(3)它们用不同的设置编译,可能编译器的版本不同,那么您将看到这种行为(resize()分配新的内存,将所有内容复制到它,然后去释放旧的内存,除了旧的内存分配在不同的运行时,所以程序barfs)。

总之,您发布的代码非常好。还有其他事情正在发生。

1

我想你在错误发生之前做了一些错误。一个std::vector::resize操作将要求记忆,并且堆是腐败的一个容易的受害者。未定义行为的坏处在于,在错误发生后(即“可能发生的任何事情”包括“无”),症状可以变为可见的一百万条执行指令。

我们有一个“调试内存管理器”,重新定义了全球分配器和可以为腐败做了很多检查:

  1. 初始化分配的内存与非明显的位模式(这是为了发现问题时,有人使用未初始化的内存,显然代码工作发现零)
  2. 添加一些“安全区”之前,每个存储块后和删除检查,它没有被覆盖(这是缓冲区溢出检测)
  3. 填充内存时具有不同的释放特定模式(这是为了尝试ca TCH读取后删除错误)
  4. 重复利用存储块和重新分配或对全球验证检查,被删除的记忆模式仍然存在(这是赶上写后删除错误)
  5. 标记每一块与__FILE__/__LINE__信息来检测谁泄漏了内存泄漏,并能够告诉谁使用删除后损坏的块。

此外,我们还有一个内存检查例程,可根据需要遍历所有内存块并检查一致性(通常我们只在分配/取消分配时执行检查)。我们也可以在绝望的情况下注销所有内存分配/释放的完整列表。

对于第(5)点不幸的是C++语法很难测试,所以我们实际上不使用new,而是使用xnew宏,这个宏最终会扩展到放置分配;这也意味着我们不能测量标准库中分配的内存块(然而,我们存储了在库中分配之前在程序中进行了分配的最后一个源代码行是什么)。

1

我是OP。

问题是来自调用函数的内存损坏。