Сбой программы при выходе из функции c ++ .... Как вы думаете, что это? - PullRequest
1 голос
/ 31 июля 2009

У меня есть код на 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.

Я думаю, что проблема с классом ниже ... std :: copy правильно в pvector operator = (const pvector & 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;
  }

Примечание: добавив & к типу возвращаемого значения, сбой все еще сохраняется. Однако после устранения утечки добавляем 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; 
      }
    }

  };

Ответы [ 11 ]

0 голосов
/ 31 июля 2009

Внутри вашей функции (funcname) или в одной из функций, вызываемых funcname, вы можете иметь некоторый код, который повреждает стек.

Наиболее «практичным» повреждением стека, с которым я столкнулся, являются копии памяти или строковые копии, когда выделенный целевой буфер не соответствует размеру копируемых данных (неправильный расчет размера с использованием sizeof и количества элементов, без учета конца терминатора строки при определении размера целевого буфера для копирования строк).

Другая возможность, встречающаяся реже: арифметика указателей, при реферировании локальных переменных или массивов и изменении их через этот указатель.

...