2015-01-26 5 views
3

Может кто-нибудь помочь мне выяснить, почему у меня ошибка времени выполнения в моем коде при использовании gnuWin32. Ошибка исчезает, когда функция GaussSeidel прокомментирована. Я попробовал онлайн-компилятор GNU GCC v4.8.3 и, похоже, там работает нормально. C++ 14 на ideone.com дал мне ошибку во время выполнения двойной свободной или коррупции. Я прикрепил простую версию моего кода, который страдает от этой ошибки. Благодарю.Двойная бесплатная или поврежденная ошибка

#include <iostream> 
#include <cmath> 

void GaussSeidel(double** const aa, double* const bb, double* xvec, const int nn, int mm) 
{ 
    int i = 0, j = 0; 
    double *ynew=NULL, *yold=NULL, EE=20.0; 
    ynew=new double[nn]; 
    yold=new double[nn]; 

    while (mm > 0 && EE>0.00001) { 
     EE=0.0; 
     for (i = 0; i < nn; i++) { 
      yold[i]=ynew[i]; 
      ynew[i] = bb[i]/aa[i][i]; 
      for (j = 0; j < nn; j++) { 
       if (j == i) continue; 
       ynew[i] = ynew[i] - (aa[i][j] * xvec[j]/ aa[i][i]); 
       xvec[i] = ynew[i]; 
      } 
      if (std::abs(ynew[i]-yold[i])>EE) EE=std::abs(ynew[i]-yold[i]); 
     } 
     mm--; 
    } 
    std::cout << mm << " " << EE << std::endl; 

    for (j = 0; j < nn; j++) 
     xvec[i] = ynew[i]; 

    delete [] ynew; 
    delete [] yold; 
} 

int main (void) 
{ 
    int i, j; 
    const int Np=100; 
    double **Infl=NULL, *Source=NULL, *FpdPhi0=NULL; 

    Source=new double[Np]; 
    FpdPhi0=new double[Np]; 
    Infl = new double *[Np]; for(i = 0; i < Np; i++) Infl[i] = new double[Np]; 

    for (j=0; j<Np; j++){ 
     for (i=0; i<Np; i++){ 
      if (i==j){ 
       Infl[j][i]=1.0; 
      } 
      else { 
       Infl[j][i]=0.0; 
      } 
     } 
     Source[j]=4.0; 
     FpdPhi0[j]=0.1; 
    } 
    GaussSeidel(Infl, Source, FpdPhi0, Np, 300); 

    for(i = 0; i < Np; i++) delete [] Infl[i]; 
    delete [] Infl; 
    delete [] Source; 
    delete [] FpdPhi0; 

    return 0; 
} 
+5

Используйте 'std :: vector' и избавьтесь от всего бесполезного управления ручной памятью. – Chad

+2

Кроме того, ваш GaussSeidel имеет утечку памяти, если второй вызов 'new []' в этой функции вызывает исключение. Избегайте всех этих проблем с помощью 'std :: vector'. – PaulMcKenzie

+0

Это хорошая идея ограничить область переменных индекса for-loop. – molbdnilo

ответ

4

Ваш последний цикл внутри функции использует i в качестве индекса, который в этот момент, вероятно, равна nn и находится вне границ. Вы, вероятно, хотели использовать переменную цикла j.

В результате, вы получаете доступ из диапазона xvec массива, что неопределенное поведение и, вероятно, коррумпированной один из других внутренне определенных массивов перед удалением его

+0

Спасибо миллиону – mokk

0

я могу определить возможный вкладчик.

ynew and yold представляют собой динамически распределенные массивы базового типа (double). Первым действием внутри функции является присвоение yold [i] = ynew [i] в ​​цикле (где i выполняется от нуля до nn-1)

Проблема в том, что оператор new по умолчанию инициализирует элементы массива , Первоначальная инициализация базовых типов (double, int, указатели и т. Д.) Фактически оставляет их неинициализированными (за исключением нескольких особых случаев, таких как статика, когда они ноль-инициализируются).

Как присвоение формы «x = y» делает так называемое преобразование rvalue-to-lvalue на y (сложный способ сказать «получить доступ к значению y, так что x может быть присвоено одно и то же значение»). Преобразование rvalue-to-lvalue имеет неопределенное поведение в неинициализированной переменной.

Вкратце: после динамического выделения ваших массивов в GaussSeidel() вам необходимо инициализировать их перед доступом к значениям элементов.

В кратчайшие сроки я не встречал никаких других очевидных проблем, связанных с неопределенным поведением.

Вместо того, чтобы обезвреживать напрямую с новыми и удаленными операторами, я также предлагаю рассмотреть использование std :: vector.

+0

Спасибо за ваш ответ. Сделаю. – mokk