programing

세그멘테이션 장애: 11

kingscode 2022. 7. 16. 15:48
반응형

세그멘테이션 장애: 11

프로그램에 문제가 있어 세그멘테이션 폴트를 검색했는데 잘 이해하지 못해서 알 수 있는 유일한 것은 아마도 접근하지 말아야 할 메모리에 접근하려고 한다는 것입니다.문제는 코드를 보고 무엇을 잘못하고 있는지 모른다는 것입니다.

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

#define   lambda   2.0
#define   g        1.0
#define   Lx       100
#define   F0       1.0
#define   Tf       10
#define   h       0.1
#define   e       0.00001

FILE   *file;

double F[1000][1000000];

void Inicio(double D[1000][1000000]) {
int i;
for (i=399; i<600; i++) {
    D[i][0]=F0;
}
}

void Iteration (double A[1000][1000000]) {
long int i,k;
for (i=1; i<1000000; i++) {
    A[0][i]= A[0][i-1] + e/(h*h*h*h)*g*g*(A[2][i-1] - 4.0*A[1][i-1] + 6.0*A[0][i-1]-4.0*A[998][i-1] + A[997][i-1]) + 2.0*g*e/(h*h)*(A[1][i-1] - 2*A[0][i-1] + A[998][i-1]) + e*A[0][i-1]*(lambda-A[0][i-1]*A[0][i-1]);
    A[1][i]= A[1][i-1] + e/(h*h*h*h)*g*g*(A[3][i-1] - 4.0*A[2][i-1] + 6.0*A[1][i-1]-4.0*A[0][i-1] + A[998][i-1]) + 2.0*g*e/(h*h)*(A[2][i-1] - 2*A[1][i-1] + A[0][i-1]) + e*A[1][i-1]*(lambda-A[1][i-1]*A[1][i-1]);
    for (k=2; k<997; k++) {
        A[k][i]= A[k][i-1] + e/(h*h*h*h)*g*g*(A[k+2][i-1] - 4.0*A[k+1][i-1] + 6.0*A[k][i-1]-4.0*A[k-1][i-1] + A[k-2][i-1]) + 2.0*g*e/(h*h)*(A[k+1][i-1] - 2*A[k][i-1] + A[k-1][i-1]) + e*A[k][i-1]*(lambda-A[k][i-1]*A[k][i-1]);
    }
    A[997][i] = A[997][i-1] + e/(h*h*h*h)*g*g*(A[0][i-1] - 4*A[998][i-1] + 6*A[997][i-1] - 4*A[996][i-1] + A[995][i-1]) + 2.0*g*e/(h*h)*(A[998][i-1] - 2*A[997][i-1] + A[996][i-1]) + e*A[997][i-1]*(lambda-A[997][i-1]*A[997][i-1]);
    A[998][i] = A[998][i-1] + e/(h*h*h*h)*g*g*(A[1][i-1] - 4*A[0][i-1] + 6*A[998][i-1] - 4*A[997][i-1] + A[996][i-1]) + 2.0*g*e/(h*h)*(A[0][i-1] - 2*A[998][i-1] + A[997][i-1]) + e*A[998][i-1]*(lambda-A[998][i-1]*A[998][i-1]);
    A[999][i]=A[0][i];
}
}

main() {
long int i,j;
Inicio(F);
Iteration(F);
file = fopen("P1.txt","wt");
for (i=0; i<1000000; i++) {
    for (j=0; j<1000; j++) {
        fprintf(file,"%lf \t %.4f \t %lf\n", 1.0*j/10.0, 1.0*i, F[j][i]);
    }
}
fclose(file);
}

시간 내주셔서 감사합니다.

이 선언:

double F[1000][1000000];

는 일반적인 x86 시스템에서 8 * 1000 * 1000000 바이트를 차지합니다.이것은 약 7.45 GB입니다.코드를 실행하려고 할 때 시스템의 메모리가 부족하여 분할 오류가 발생할 수 있습니다.

어레이는 약 8GB의 메모리(1,000 x 1,000,000 x size of (2배)바이트)를 사용하고 있습니다.그게 당신 문제의 한 요인이 될 수도 있어요.이것은 스택 변수가 아니라 전역 변수이기 때문에 문제가 없을 수 있지만 여기서는 한계를 초과하고 있습니다.

그렇게 많은 데이터를 파일에 쓰려면 시간이 좀 걸릴 거예요.

파일이 정상적으로 열렸는지 확인하지 않고 문제의 원인이 될 수도 있습니다(실패했을 경우 세그멘테이션 장애일 가능성이 매우 높습니다).

1,000,000과 1,000,000에 대해 명명된 상수를 몇 가지 소개해야 합니다. 이 상수는 무엇을 나타냅니까?

. 계산하기 위해서는 '함수'를 할 수 .inlineC99 ( C++ ) 。을 사용법

C99는 해야 합니다.main() 타입 바람직하게는 「환원」)을 void하지 의 경우argc ★★★★★★★★★★★★★★★★★」argv

int main(void)

상태의 호기심으로 오카렌스를 ROWS로 후 ROWS의 1000000을 생성했습니다.enum { ROWS = 1000, COLS = 10000 };(100명)컴파일 옵션 세트하지 않은 컴파일 옵션 컴파일되도록 몇 .static 및 배열 앞에 .filemain (오류체크);; " " " "fopen()등 ) 。

그런 다음 두 번째 복사본을 만들고 반복 계산을 수행하는 인라인 함수를 만들고 두 번째 복사본을 만들어 첨자 계산을 수행했습니다.즉, 이 괴상한 표현은 1회밖에 쓰여지지 않습니다.이것은 일관성을 확보하기 위해 매우 바람직합니다.

#include <stdio.h>

#define   lambda   2.0
#define   g        1.0
#define   F0       1.0
#define   h        0.1
#define   e        0.00001

enum { ROWS = 1000, COLS = 10000 };

static double F[ROWS][COLS];

static void Inicio(double D[ROWS][COLS])
{
    for (int i = 399; i < 600; i++) // Magic numbers!!
        D[i][0] = F0;
}

enum { R = ROWS - 1 };

static inline int ko(int k, int n)
{
    int rv = k + n;
    if (rv >= R)
        rv -= R;
    else if (rv < 0)
        rv += R;
    return(rv);
}

static inline void calculate_value(int i, int k, double A[ROWS][COLS])
{
    int ks2 = ko(k, -2);
    int ks1 = ko(k, -1);
    int kp1 = ko(k, +1);
    int kp2 = ko(k, +2);

    A[k][i] = A[k][i-1]
            + e/(h*h*h*h) * g*g * (A[kp2][i-1] - 4.0*A[kp1][i-1] + 6.0*A[k][i-1] - 4.0*A[ks1][i-1] + A[ks2][i-1])
            + 2.0*g*e/(h*h) * (A[kp1][i-1] - 2*A[k][i-1] + A[ks1][i-1])
            + e * A[k][i-1] * (lambda - A[k][i-1] * A[k][i-1]);
}

static void Iteration(double A[ROWS][COLS])
{
    for (int i = 1; i < COLS; i++)
    {
        for (int k = 0; k < R; k++)
            calculate_value(i, k, A);
        A[999][i] = A[0][i];
    }
}

int main(void)
{
    FILE *file = fopen("P2.txt","wt");
    if (file == 0)
        return(1);
    Inicio(F);
    Iteration(F);
    for (int i = 0; i < COLS; i++)
    {
        for (int j = 0; j < ROWS; j++)
        {
            fprintf(file,"%lf \t %.4f \t %lf\n", 1.0*j/10.0, 1.0*i, F[j][i]);
        }
    }
    fclose(file);
    return(0);
}

이 프로그램은 다음 위치에 씁니다.P2.txt대신P1.txt두 프로그램을 모두 실행하여 출력 파일을 비교했는데 출력은 동일했습니다.대부분 유휴 머신(MacBook Pro, 2.3GHz Intel Core i7, 16 GiB 1333 MHz RAM, Mac OS X 10.7.5, GCC 4.7.1)에서 프로그램을 실행했을 때, 합리적으로 실행되었지만 완전히 일관된 타이밍은 아니었습니다.

Original   Modified
6.334s      6.367s
6.241s      6.231s
6.315s     10.778s
6.378s      6.320s
6.388s      6.293s
6.285s      6.268s
6.387s     10.954s
6.377s      6.227s
8.888s      6.347s
6.304s      6.286s
6.258s     10.302s
6.975s      6.260s
6.663s      6.847s
6.359s      6.313s
6.344s      6.335s
7.762s      6.533s
6.310s      9.418s
8.972s      6.370s
6.383s      6.357s

그러나 거의 모든 시간이 디스크 I/O에 소비됩니다.디스크 I/O를 마지막 데이터 행으로 줄였으므로 외부 I/O는for루프가 되었습니다.

for (int i = COLS - 1; i < COLS; i++)

시간이 대폭 단축되고 일관성이 크게 향상되었습니다.

Original    Modified
0.168s      0.165s
0.145s      0.165s
0.165s      0.166s
0.164s      0.163s
0.151s      0.151s
0.148s      0.153s
0.152s      0.171s
0.165s      0.165s
0.173s      0.176s
0.171s      0.165s
0.151s      0.169s

무서운 표현을 한 번 쓰는 것으로부터 코드화를 간략하게 하는 것은 매우 유익하다고 생각합니다.원래 프로그램보다 그 프로그램을 유지하는 게 더 낫겠어요.

어떤 시스템에서 실행하고 있습니까?일종의 디버거(gdb, Visual Studio의 디버거 등)에 액세스할 수 있습니까?

그러면 귀중한 정보를 얻을 수 있을 겁니다. 예를 들어 프로그램이 충돌하는 코드 라인이...또, 메모리의 양이 엄청날 수도 있습니다.

또한 숫자 제한을 명명된 정의로 바꾸는 것이 좋습니다.

따라서:

#define DIM1_SZ 1000
#define DIM2_SZ 1000000

어레이 치수 제한을 참조할 때는 언제든지 사용하십시오.이렇게 하면 입력 오류를 방지할 수 있습니다.

efence와 연결된 Valgrind로 프로그램을 실행합니다.그러면 포인터가 참조되지 않은 위치를 알 수 있으며, 사용자가 알려준 오류를 모두 수정하면 문제를 해결할 수 있습니다.

언급URL : https://stackoverflow.com/questions/12762944/segmentation-fault-11

반응형