我有一个c ++代码,我使用MSC9来编译它。 它会随机崩溃。例如,如果使用``从Perl调用它会崩溃,但是当从命令行或从Ultimate ++调用它时它不会崩溃。
我的意思是从perl调用它,例如。 f.exe arg1 arg2 arg3
堆栈跟踪显示不多。逐行跟踪程序证明程序在返回时失败...
就像那样
int funcname()
{
return 0; <-- crashing after that...
}
我猜堆栈已损坏,堆栈解除后会崩溃..
可能导致什么? 该程序使用pcre,stl和迭代器。迭代器可以打破堆栈吗? 你会怎么看到这样的错误?
可以是编译器错误吗?
注意:调试版本不会崩溃,只会发布版本......
这个错误似乎与这个pvector类有关。
我有一个与此类似的结构:
struct complexstr
{
pvector<int> v;
string v2;
hash_map<string> hm;
vector<string> vs; // similar
int i;
};
似乎失败了,因为这一行:
complexstr s1;
complexstr s2;
s2=s1; // it seems to fail here, if this is not there... there is no error.
我认为问题出在下面的课程...... pve :: copy在pvector operator =(const pvector&amp; pv)中是正确的,对吧?
pvector是一个perl兼容的向量...它的索引可能大于向量的分配大小。
UPDATE1: 我收到了有关任务泄漏的建议。 我改变了作业...... 这就是它现在的样子:
pvector& operator=(const pvector &pv)
{
delete [] m_rgArray;
m_rgArray=new value_type[pv.allocated];
m_nIndex=pv.m_nIndex;
allocated=pv.allocated;
std::copy(pv.m_rgArray, pv.m_rgArray + pv.allocated, m_rgArray);
return *this;
}
注意:添加&amp;对于返回类型,崩溃仍然存在。 但是,删除泄漏后,添加delete [] m_rgArray; , 该程序不再崩溃。我不明白。据我所知泄漏 不要导致崩溃。所以这个问题似乎已经解决了(?)。问号显示我的惊讶。 UPDATE2: 不,问题又回来了。它刚刚消失了一段时间。 Update3:我想我已经找到了。我使用Microsoft调试工具中的一个名为gflags.exe和windbg.exe的实用程序来查找确切位置。 我使用gflags.exe / p / enable myprog.exe / full打开堆错误的异常。 目前,我认为该错误是由FindClose(句柄)引起的;其中handle是一个随机值,而不是初始值。
旧版本:
template<class _Ty>
class pvector
{
public:
_Ty * m_rgArray; // Declare array
int m_nIndex; // Index to array
int allocated;
_Ty undefvalue;
typedef _Ty value_type;
typedef value_type & reference;
typedef const value_type & const_reference;
typedef custom_iterator<_Ty> iterator;
typedef custom_iterator<_Ty> const_iterator;
typedef int difference_type;
typedef int size_type;
//typedef typename pvector_type_traits<_Ty>::default_value default_value;
pvector() : m_nIndex(0)
{ // init index to 0
m_rgArray = new value_type[10];
allocated = 10;
fill(0);
}
pvector(size_type s) : m_nIndex(0)
{ // init index to 0
size_type defsize = 10;
if (s>10)
{
defsize = s;
}
m_rgArray = new value_type[defsize];
allocated = defsize;
fill(0);
}
pvector(pvector const& pv)
: m_rgArray(new value_type[pv.allocated]),
m_nIndex(pv.m_nIndex),allocated(pv.allocated)
{
std::copy(pv.m_rgArray, pv.m_rgArray + pv.allocated, m_rgArray);
}
pvector operator=(const pvector &pv)
{
m_rgArray=new value_type[pv.allocated];
m_nIndex=pv.m_nIndex;
allocated=pv.allocated;
std::copy(pv.m_rgArray, pv.m_rgArray + pv.allocated, m_rgArray);
return *this;
}
void clear()
{
m_nIndex=0;
fill(allocated);
}
~pvector() {
delete []m_rgArray;
}
size_type size() const
{ // return length of sequence
return m_nIndex;
}
size_type max_size() const
{ // return maximum possible length of sequence
return 0;
}
void fill(size_type si)
{
for (size_type i = si;i<allocated;i ++ )
{
m_rgArray[i] = pvector_type_traits<_Ty>::default_value();
}
}
bool empty() const
{ // test if sequence is empty
return (m_nIndex > 0 ? false : true);
}
iterator begin()
{ // return iterator for beginning of mutable sequence
return iterator(&m_rgArray[0]);
}
const_iterator begin() const
{
return const_iterator(&m_rgArray[0]);
}
iterator end()
{ // return iterator for end of mutable sequence
return iterator(&m_rgArray[m_nIndex]);
}
const_iterator end() const
{
return const_iterator(&m_rgArray[m_nIndex]);
}
reference operator[](size_type i)
{
if (m_nIndex>i)
{
return m_rgArray[i];
}
else if (i >= allocated)
{
resize(i * 2);
}
m_nIndex = i + 1;
return m_rgArray[i];
}
void resize(size_type s)
{
value_type * m_rgArray2;
size_type old_allocated = allocated;
allocated = s;
m_rgArray2 = new value_type[allocated];
//if (allocated>m_nIndex)
//{
// m_nIndex=allocated;
// }
// cout <<"m_nIndex" << m_nIndex << "allocated" << allocated << endl;
if (m_nIndex>allocated)
{
m_nIndex=allocated;
}
for (size_type i = 0;i<m_nIndex;i ++ )
{
m_rgArray2[i] = m_rgArray[i];
}
delete []m_rgArray;
m_rgArray = m_rgArray2;
fill(old_allocated);
}
reference back()
{
return &m_rgArray[m_nIndex - 1];
}
const_reference back() const
{
return m_rgArray[m_nIndex - 1];
}
void push_back(const _Ty &_Val)
{ // insert element at end
if (size() < allocated)
m_rgArray[m_nIndex ++ ] = _Val;
else
{
resize(allocated * 2);
m_rgArray[m_nIndex ++ ] = _Val;
}
}
};
答案 0 :(得分:12)
它可能是一个缓冲区溢出破坏堆栈。如果在运行函数时在本地定义的缓冲区外写入,它可以覆盖返回地址,然后从函数返回将触发程序崩溃。
您应该查找使用本地(堆栈分配)变量地址操作的语句 - 缓冲区溢出很可能是导致问题的原因。
答案 1 :(得分:3)
我能想到的可能性:
答案 2 :(得分:3)
此代码有很多错误:
命名 - 我已经使用_Ty
指出了问题,但为什么有些成员会以m_
开头,而其他成员则不会。一些局部变量也以m_
开头。不好。
分配操作不会返回引用 - 正如已经指出的那样。
分配操作有内存泄漏,在第一行,你分配给已经有内容的m_rgArray - 这些都是泄露的。
这是初学者。这些都不会导致崩溃,但它们都需要修复。为了解决所有问题,我会重新开始,一次编写一个函数,再加上测试。运行测试,如果有效,请编写下一个函数,下一个测试,依此类推。值得在这样的模板类中投入大量精力,因为如果它们是正确的,它们非常有用,但如果错误则是持续痛苦的根源。
答案 3 :(得分:2)
你有任何基于堆栈的对象与非平凡的析构函数?根据您的调试器,可能很难判断它们何时执行。除了其他评论中提到的所有内容之外,它可能与此相关。
答案 4 :(得分:1)
我假设以下函数有更多代码
int funcname()
{
return 0; <-- crashing after that...
}
当函数返回时,任何堆栈变量都会调用它们的析构函数。崩溃很可能发生在其中一个析构函数中。
如何追踪它:
将断点放在函数中声明的任何变量的析构函数中。逐步完成每个析构函数。请记住,当一个析构函数被调用时,会有一大堆来自基类的析构函数,这些析构函数会自动被调用,并且腐败可能出现在任何一个中。
答案 5 :(得分:1)
关于您的运营商的另一条评论=
我不知道是不是这会给你带来问题,但是由于它似乎有内存损坏的问题,它可能会成为明星。
答案 6 :(得分:0)
在你的函数(funcname)或funcname调用的函数之一中你可能有一些破坏堆栈的代码。
我遇到的大多数“实践”堆栈损坏是内存副本或字符串副本,当分配的目标缓冲区不符合要复制的数据的大小时(使用sizeof和元素数量计算大小,不考虑结束-of-string终止符,用于调整目标缓冲区的大小以进行字符串复制。)
另一种可能性,经常遇到:指针aritmetics,引用局部变量或数组并通过该指针更改它们。
答案 7 :(得分:0)
由于您的详细信息并非特定于崩溃,我建议您使用IDE调试应用程序: 在ProjectProperties-&gt; ConfigurationProperties-&gt; Debugging中,将Command和Command Arguments设置为perl / ultimate ++应用程序。在调试模式下编译并将断点放在您怀疑崩溃的位置。找到问题并在崩溃本身上提出有意义的信息应该相当简单。
答案 8 :(得分:0)
您的赋值运算符应返回引用:
pvector& operator=(const pvector &pv) {
我怀疑这会导致问题,但请试一试。
答案 9 :(得分:0)
调试器说什么?在返回行之后,它会遍历所有析构函数,使对象超出作用域,其中一个几乎肯定会搞砸。 因此,在返回行放置一个断点,然后逐步调试,直到崩溃为止。
答案 10 :(得分:0)
我的猜测是你的pvector在调整大小期间超越一个数组的问题。我正在尝试阅读代码以查找是否属实,但我没有看到任何明显的东西。如果您真正想要的是一个增长到适合访问索引的向量,那么您不需要自己编写整个事物。您可以扩展std :: vector,只需使用reserve()/ resize()方法,让STL处理所有复制和内存管理以及迭代器。以下应该有效:
template<typename StoredType>
class pvector : public std::vector<StoredType>
{
public:
typedef typename std::vector<StoredType, std::allocator<StoredType> >::reference reference;
typedef typename std::vector<StoredType, std::allocator<StoredType> >::size_type size_type;
reference at(size_type n)
{
size_type need = n+1;
if(need > std::vector<StoredType>::capacity())
{
std::vector<StoredType>::reserve(need * 2);
std::vector<StoredType>::resize(need);
}
else if(need > std::vector<StoredType>::size())
{
std::vector<StoredType>::resize(need);
}
return std::vector<StoredType>::at(n);
}
reference operator[](size_type n)
{
return at(n);
}
};
我在Linux上使用GCC 4.1.2进行了测试,所以希望它也可以在Windows上编译。
编辑:这是一个不继承的新版本,因为看起来专家认为这不是一个好主意(我学到了新东西,但是)。您可以实现所需的其余方法,只需传递给m_vector:
template<typename StoredType>
class pvector
{
public:
typedef StoredType& reference;
typedef int size_type;
reference at(size_type n)
{
int need = n+1;
if(need >= m_vector.capacity())
{
m_vector.reserve(need * 2);
m_vector.resize(need);
}
else if(need >= m_vector.size())
{
m_vector.resize(need);
}
return m_vector.at(n);
}
reference operator[](size_type n)
{
return at(n);
}
size_type capacity() { return m_vector.capacity(); }
size_type size() { return m_vector.size(); }
private:
std::vector<StoredType> m_vector;
};