Hi, I have a c++ code, I use MSC9 to compile it. It keeps crashing randomly. For example it crashes if it is called from Perl using `` but it does not crash when It is called from command line or from Ultimate++.
I mean calling it from perl eg. f.exe arg1 arg2 arg3
Stack trace does not show much. Tracing the program line by line proved that the program fails at the end when returning...
So it is like that
int funcname()
{
return 0; <-- crashing after that...
}
I guess the stack is damaged, and after the stack is unwound, it crashes..
What can cause it? The program uses pcre, stl and iterators. Can an iterator break the stack? How would you catch an error like that?
Can it be a compiler bug?
Note: the debug version does not crash, only the release version...
The bug seems to be related this pvector class.
I have a struct similar to this:
struct complexstr
{
pvector<int> v;
string v2;
hash_map<string> hm;
vector<string> vs; // similar
int i;
};
It seems to fail because this line:
complexstr s1;
complexstr s2;
s2=s1; // it seems to fail here, if this is not there... there is no error.
I think the problem is with the class below... std::copy is correct in pvector operator=(const pvector &pv), right?
pvector is a perl compatible vector... Its indexes can be larger than allocated size of the vector.
Update1: I received suggestions that there is a leak in the assignment. I changed the assignment... That is how it looks now:
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;
}
Note: by adding & to the return type, the crash still remained. However, after removing the leak, adding delete [] m_rgArray; , the program no longer crashes. I do not understand. As far as I know leaks do not cause crashes. So the problem seems to be solved(?). The question mark shows my surprise. Update2: No, the problem came back. It just disappeared for a while. Update3: I think I have found it. I used an utility from Microsoft debugging tools called gflags.exe and windbg.exe to find the exact location. I used gflags.exe /p /enable myprog.exe /full to turn on exceptions for heap bugs.. At the moment, I think the bug was caused by FindClose(handle); where handle was a random value, not initialiased.
Old version:
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;
}
}
};