Ошибка сегментации в моей C-программе - PullRequest
1 голос
/ 03 мая 2010

Я не понимаю, почему это вызвало бы ошибку сегмента. Есть идеи?

Это функция, которая возвращает сигнал, чтобы остановить программу (плюс другая функция, которая вызывается в этом):

double bisect(double A0,double A1,double Sol[N],double tol,double c)
{
  double Amid,shot;

  while (A1-A0 > tol) {
    Amid = 0.5*(A0+A1);

    shot = shoot(Sol, Amid, c);

    if (shot==2.*Pi) {
      return Amid;
    }

    if (shot > 2.*Pi){
      A1 = Amid;
    }
    else if (shot < 2.*Pi){
      A0 = Amid;
    }
  }

  return 0.5*(A1+A0);
}

double shoot(double Sol[N],double A,double c)
{
  int i,j;

  /*Initial Conditions*/
  for (i=0;i<buff;i++)
    {
      Sol[i] = 0.;
    }
  for (i=buff+l;i<N;i++)
    {
      Sol[i] = 2.*Pi;
    }
  Sol[buff]= 0;
  Sol[buff+1]= A*exp(sqrt(1+3*c)*dx);


  for (i=buff+2;i<buff+l;i++)
    {
      Sol[i] = (dx*dx)*( sin(Sol[i-1]) + c*sin(3.*(Sol[i-1])) )
 - Sol[i-2] + 2.*Sol[i-1];
    }

  return Sol[i-1];
}

значения buff, l, N определены с помощью оператора #define. l = 401, бафф = 50, N = 2000

Вот полный код:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define w 10    /*characteristic width of a soliton*/
#define dx 0.05 /*distance between lattice sites*/
#define s (2*w)/dx  /*size of soliton shape*/
#define l (int)(s+1)   /*array length for soliton*/
#define N (int)2000    /*length of field array--lattice sites*/
#define Pi (double)4*atan(1)
#define buff (int)50


double shoot(double Sol[N],double A,double c);
double bisect(double A0,double A1,double Sol[N],double tol,double c);
void super_pos(double antiSol[N],double Sol[N],double phi[][N]);
void vel_ver(double phi[][N],double v,double c,int tsteps,double dt);



int main(int argc, char **argv)
{
  double c,Sol[N],antiSol[N],A,A0,A1,tol,v,dt;
  int  tsteps,i;
  FILE *fp1,*fp2,*fp3;

  fp1 = fopen("soliton.dat","w");
  fp2 = fopen("final-phi.dat","w");
  fp3 = fopen("energy.dat","w");
  printf("Please input the number of time steps:");
  scanf("%d",&tsteps);
  printf("Also, enter the time step size:");
  scanf("%lf",&dt);
  do{
    printf("Please input the parameter c in the interval [-1/3,1]:");
    scanf("%lf",&c);}
  while(c < (-1./3.) || c > 1.);
  printf("Please input the inital speed of eiter soliton:");
  scanf("%lf",&v);

  double phi[tsteps+1][N];

  tol = 0.0000001;
  A0 = 0.;
  A1 = 2.*Pi;
  A = bisect(A0,A1,Sol,tol,c);
  shoot(Sol,A,c);
  for (i=0;i<N;i++)
    {
      fprintf(fp1,"%d\t",i);
      fprintf(fp1,"%lf\n",Sol[i]);
    }
  fclose(fp1);
  super_pos(antiSol,Sol,phi);
  /*vel_ver(phi,v,c,tsteps,dt);
  for (i=0;i<N;i++){
    fprintf(fp2,"%d\t",i);
    fprintf(fp2,"%lf\n",phi[tsteps][i]);
    }*/


}


double shoot(double Sol[N],double A,double c)
{
  int i,j;

  /*Initial Conditions*/
  for (i=0;i<buff;i++)
    {
      Sol[i] = 0.;
    }
  for (i=buff+l;i<N;i++)
    {
      Sol[i] = 2.*Pi;
    }
  Sol[buff]= 0;
  Sol[buff+1]= A*exp(sqrt(1+3*c)*dx);


  for (i=buff+2;i<buff+l;i++)
    {
      Sol[i] = (dx*dx)*( sin(Sol[i-1]) + c*sin(3.*(Sol[i-1])) )
    - Sol[i-2] + 2.*Sol[i-1];
    }

  return Sol[i-1];
}


double bisect(double A0,double A1,double Sol[N],double tol,double c)
{
  double Amid,shot;

  while (A1-A0 > tol) {
    Amid = 0.5*(A0+A1);

    shot = shoot(Sol, Amid, c);

    if (shot==2.*Pi) {
      return Amid;
    }

    if (shot > 2.*Pi){
      A1 = Amid;
    }
    else if (shot < 2.*Pi){
      A0 = Amid;
    }
  }

  return 0.5*(A1+A0);
}


void super_pos(double antiSol[N],double Sol[N],double phi[][N])
{
  int i;

  /*for (i=0;i<N;i++)
    {
    phi[i]=0;
    }

  for (i=buffer+s;i<1950-s;i++)
    {
      phi[i]=2*Pi;
      }*/

  for (i=0;i<N;i++)
    {
      antiSol[i] = Sol[N-i];
    }

  /*for (i=0;i<s+1;i++)
    {
      phi[buffer+j] = Sol[j];
      phi[1549+j] = antiSol[j];
      }*/

  for (i=0;i<N;i++)
    {
      phi[0][i] = antiSol[i] + Sol[i] - 2.*Pi;
    }

}

/* This funciton will set the 2nd input array to the derivative at the time t, for all points x in the lattice */
void deriv2(double phi[][N],double DphiDx2[][N],int t)
{
  //double SolDer2[s+1];
  int x;
  for (x=0;x<N;x++)
    {
      DphiDx2[t][x] = (phi[buff+x+1][t] + phi[buff+x-1][t] - 2.*phi[x][t])/(dx*dx);
    }

  /*for (i=0;i<N;i++)
    {
      ptr[i] = &SolDer2[i];
      }*/

  //return DphiDx2[x];
  }




void vel_ver(double phi[][N],double v,double c,int tsteps,double dt)
{
  int t,x;
  double d1,d2,dp,DphiDx1[tsteps+1][N],DphiDx2[tsteps+1][N],dpdt[tsteps+1][N],p[tsteps+1][N];

  for (t=0;t<tsteps;t++){
    if (t==0){
      for (x=0;x<N;x++){//inital conditions
    deriv2(phi,DphiDx2,t);
    dpdt[t][x] = DphiDx2[t][x] - sin(phi[t][x]) - sin(3.*phi[t][x]);
    DphiDx1[t][x] = (phi[t][x+1] - phi[t][x])/dx;
    p[t][x] = -v*DphiDx1[t][x];
      }
    }
    for (x=0;x<N;x++){//velocity-verlet
      phi[t+1][x] = phi[t][x] + dt*p[t][x] + (dt*dt/2)*dpdt[t][x];
      p[t+1][x] = p[t][x] + (dt/2)*dpdt[t][x];
      deriv2(phi,DphiDx2,t+1);
      dpdt[t][x] = DphiDx2[t][x] - sin(phi[t+1][x]) - sin(3.*phi[t+1][x]);
      p[t+1][x] += (dt/2)*dpdt[t+1][x];
    }
  }  
}

Итак, это действительно не из-за того, что я переписал конец массива Sol. Я прокомментировал обе функции, которые, как я подозревал, вызывал проблему (разделить на две части) и добавил функцию печати. Происходят две вещи. Когда у меня есть код, как показано ниже:

double A,Pi,B,c;

c=0;
Pi = 4.*atan(1.);
A = Pi;
B = 1./4.;
printf("%lf",B);
B = shoot(Sol,A,c);
printf("%lf",B);

Я получаю ошибку от функции, стреляй. Однако, если я уберу функцию съемки, чтобы у меня было:

double A,Pi,B,c;

c=0;
Pi = 4.*atan(1.);
A = Pi;
B = 1./4.;
printf("%lf",B);

это дает мне ошибку в печати ... Почему!?

Ответы [ 3 ]

1 голос
/ 03 мая 2010

Лично я думаю, что использование #define для этих констант делает вашу функцию менее пригодной для повторного использования. Почему бы не передать это? По крайней мере, таким образом пользователи вашей функции узнают, что нужно, глядя на функцию.

Я вижу магические числа во многих местах. Мне совсем не важен этот метод.

1 голос
/ 04 мая 2010

Итак, это было решено. Проблема была с памятью. Я использовал несколько массивов большого размера ph [tsteps + 1] [N] (N = 2000) и тому подобное. Когда tsteps поступил от пользовательского (моего) ввода, он был порядка 20000. Таким образом, перегрузка памяти вызвала сбой программы во время выполнения. Спасибо за все предложения, вы все.

1 голос
/ 03 мая 2010

Возможно, вы пишете после конца массива Sol?

Я предлагаю начать с использования отладчика, такого как gdb, чтобы выяснить, какая строка вызывает ошибку сегментации.

...