2017-05-16 1 views
-2

저는 C++을 사용하여 라플라스 방정식을 풀고 있습니다. 저는 압력계 인 P를 풀고 있습니다. 내 코드에서, 당신은 아래에서 볼 수 있습니다, P는 x와 y의 함수입니다. 나는 길이 nx와 ny의 2 차원 배열로 선언했다.스택 스매싱이 감지되었습니다. C++. 라플라스 방정식을 푸십시오.

마지막 행렬 결과, P가 올바르다. 내가 "의 printf"를 사용하여이 행렬 P를 인쇄하려고 할 때 숫자가 완벽에 있는데도 그러나, 나는이 같은 오류가있어 :

*** stack smashing detected *** 
/bin/bash: line 1: 11738 Aborted 

을 아래에 내 프로그램입니다 : 처음에는

#include <cmath> 
#include <stdio.h> 
const int nx = 5; // number of elements in x-direction 
const int ny = 5; // number of elements in x-direction 
const int niter = 100; //# of iterations 

int main(){ 
    double dx = 2/double((nx-1)); 
    double dy = 1/double((ny-1)); 
    int xmax = 2; int xmin = 0; 
    int ymax = 1; int ymin = 0; 
    double p[nx][ny]; 
    double pn[nx][ny]; 
    double x[nx]; 
    double y[ny]; 

    //populate p with zeros  
    for (int xi = 1; xi <=nx;xi++){ 
     for (int yi = 1;yi<=ny;yi++){ 
      p[xi][yi] = 0;   
     } 
    } 

    //populate x and y 

    //X 
    for (int xnum = 1; xnum <=nx; xnum++){ 
     x[1] = 0; 
     x[xnum+1] = x[xnum] + dx; 
    } 

    //Y 
    for (int ynum = 1; ynum <=ny; ynum++){ 
     y[1] = 0; 
     y[ynum+1] = y[ynum] + dy; 
    } 

    //initial condition 

    for (int yrange = 1; yrange<=ny;yrange++){ 
     p[nx][yrange] = y[yrange]; 
    } 

    //SOLVING FOR P  

    for (int iter = 1; iter<=niter; iter++){ 
     //copy values 
     for (int xiter= 1; xiter<=nx;xiter++){ 
      for (int yiter = 1; yiter<=ny;yiter++){ 
       pn[xiter][yiter]=p[xiter][yiter]; 
      } 
     } 
     //main loop 
     for (int i = 2; i<=nx-1;i++){ 
      for (int j = 2; j<=ny-1;j++){ 
       p[i][j] = ((pow(dy,2)*(pn[i+1][j]+pn[i-1][j]))+(pow(dx,2)*(p[i][j+1]+pn[i][j-1])))/(2*(pow(dx,2)+pow(dy,2))); 
      } 
     } 

     for (int xrange = 2; xrange<=nx-1;xrange++){ 
      p[xrange][1] = p[xrange][2]; 
      p[xrange][ny] = p[xrange][ny-1]; 
     } 

    } 

    //Testing matrix 

     for (int x = 1; x<=nx;x++){ 
      for (int y =1; y<=ny;y++){ 
      printf("%1.3f\t",p[x][y]); 
      } 
     printf("\n"); 
     } 

return 0; 
} 

는, 반복 횟수가 너무 많아서 문제라고 생각했습니다. 즉 niter가 너무 높기 때문에 낮추기로 결정합니다. 여전히 같은 오류가 있습니다. 나 좀 도와 줄 수있어? 행렬 P의 출력 결과가 정확하므로 P를 해결할 때 논리가 아니라고 생각합니다. 어떤 도움도 정말 감사합니다. 감사합니다!

+1

결과를 인쇄 할 수 없을 때 결과가 정확하다는 것을 어떻게 알 수 있습니까? – user463035818

+0

C++ 배열의 원점은 0입니다. 루프의 원점 1을 사용하여 초기화되지 않은 것처럼 보입니다. – user4581301

+0

안녕하세요, 정확한 조건으로 Matlab에서 코딩 된 유사한 프로그램이 있는데, Matlab에서 행렬을 인쇄하고 숫자가 정확하다는 것을 알았습니다. – mle0312

답변

2

범위를 벗어남에 따라 루프가 정의되지 않은 동작 인 nx이됩니다. 인덱싱은 0에서 시작하여 i < nx까지 진행됩니다.

:

for (int xi = 1; xi <= nx; xi++){ 
    for (int yi = 1; yi <= ny; yi++){ 
     p[xi][yi] = 0;   
    } 
} 

for (int xi = 0; xi < nx; xi++){ 
    for (int yi = 0; yi < ny; yi++){ 
     p[xi][yi] = 0;   
    } 
} 

다른 모든 루프에 대해 동일해야합니다. 프로그램이 잘 진행된 것처럼 보일 수 있으며 UB의 원인과 관련이없는 곳에서는 프로그램이 중단 될 수 있습니다. 정의되지 않은 동작이 발생하면 아무 것도 발생하지 않을 수 있으므로 실제로 충돌이 발생하여이를 고칠 수있는 기회가 주어집니다.

추신 : 정말로 원한다면 (왜, 아마도 FORTRAN 신봉자입니까?) 루프를 1에서 시작할 수 있습니다.하지만 루프를 불필요하게 읽기 어렵게 만들기 때문에 권장하지 않습니다. 발생하기 쉬운 오류. 예를 들어, 다음 루프에서 오류가 쉽게 간과 할 수 있습니다

//copy values (!!! WRONG CODE !!! spot the error to win a FORTRAN fanshirt) 
    for (int xiter= 1; xiter < nx+1; xiter++){ 
     for (int yiter = 1; yiter < ny+1; yiter++){ 
      pn[xiter-1][yiter-1] = p[xiter][yiter-1]; 
     } 
    } 

을 ... BTW는 어떤 방식으로 FORTRAN을 비난 할 의도는 없습니다. 사실 FORTRAN을 좋아하지만 실제로는 다른 언어입니다. (사실 1에서 인덱스를 시작하는 곳은 제가 아는 유일한 언어입니다).

+0

감사합니다. 나는 1 개의 질문이 더있다 : 나는 C++이 0에서부터 시작한다는 것을 안다. 그러나 반복문에서 1에서 시작하도록 지정할 수있다. 아니면 그렇게하고 싶다면 nx + 1까지 반복해야합니다. 다시 한 번 감사드립니다 – mle0312

+0

@ mle0312 왜 그렇게하고 싶습니까? 예를 들어 대답을 편집했습니다. – user463035818

관련 문제