linux上的分段错误(gcc)

时间:2014-07-03 17:57:03

标签: c linux gcc valgrind

我正在调试一个数字程序。它在Windows(Visual Studio编译器)上运行良好,给出了正确的结果。

不幸的是在使用gcc的Linux(Ubuntu 12.04 x64)上,程序在计算一部分后会产生分段错误(我得到了部分结果)。

我尝试使用Valgrind来调试它,并找到一个可能出现错误的地方。

结果是:

==19565== Memcheck, a memory error detector
==19565== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==19565== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==19565== Command: ./a.out
==19565==
==19565== Invalid read of size 8
==19565==    at 0x402E50: MAXN(double, int, double, int*, double*,
int, double*, double*, double*, double*, int*, int*, double, double*,
int*, double) (in /home/muniek/Desktop/c_code/a.out)
==19565==    by 0x401991: main (in /home/muniek/Desktop/c_code/a.out)
==19565==  Address 0x54f0958 is not stack'd, malloc'd or (recently) free'd
==19565==
==19565== Invalid read of size 8
==19565==    at 0x402E65: MAXN(double, int, double, int*, double*,
int, double*, double*, double*, double*, int*, int*, double, double*,
int*, double) (in /home/muniek/Desktop/c_code/a.out)
==19565==    by 0x401991: main (in /home/muniek/Desktop/c_code/a.out)
==19565==  Address 0x54f0950 is not stack'd, malloc'd or (recently) free'd
==19565==
==19565== Invalid read of size 8
==19565==    at 0x402E85: MAXN(double, int, double, int*, double*,
int, double*, double*, double*, double*, int*, int*, double, double*,
int*, double) (in /home/muniek/Desktop/c_code/a.out)
==19565==    by 0x401991: main (in /home/muniek/Desktop/c_code/a.out)
==19565==  Address 0x54f0958 is not stack'd, malloc'd or (recently) free'd
==19565==
==19565== Invalid read of size 8
==19565==    at 0x402E9A: MAXN(double, int, double, int*, double*,
int, double*, double*, double*, double*, int*, int*, double, double*,
int*, double) (in /home/muniek/Desktop/c_code/a.out)
==19565==    by 0x401991: main (in /home/muniek/Desktop/c_code/a.out)
==19565==  Address 0x54f0960 is not stack'd, malloc'd or (recently) free'd
==19565==
==19565== Invalid read of size 8
==19565==    at 0x402D82: MAXN(double, int, double, int*, double*,
int, double*, double*, double*, double*, int*, int*, double, double*,
int*, double) (in /home/muniek/Desktop/c_code/a.out)
==19565==    by 0x401991: main (in /home/muniek/Desktop/c_code/a.out)
==19565==  Address 0x54f0978 is 8 bytes before a block of size 1,696 alloc'd
==19565==    at 0x4C29DB4: calloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19565==    by 0x404CC0: dvector(int, int) (in
/home/muniek/Desktop/c_code/a.out)
==19565==    by 0x400A62: main (in /home/muniek/Desktop/c_code/a.out)
==19565==
==19565==
==19565== HEAP SUMMARY:
==19565==     in use at exit: 1,704 bytes in 3 blocks
==19565==   total heap usage: 1,228,705 allocs, 1,228,702 frees,
9,826,265,416 bytes allocated
==19565==
==19565== 568 bytes in 1 blocks are still reachable in loss record 1 of 3
==19565==    at 0x4C2B6CD: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19565==    by 0x519D20A: __fopen_internal (iofopen.c:76)
==19565==    by 0x401100: main (in /home/muniek/Desktop/c_code/a.out)
==19565==
==19565== 568 bytes in 1 blocks are still reachable in loss record 2 of 3
==19565==    at 0x4C2B6CD: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19565==    by 0x519D20A: __fopen_internal (iofopen.c:76)
==19565==    by 0x401116: main (in /home/muniek/Desktop/c_code/a.out)
==19565==
==19565== 568 bytes in 1 blocks are still reachable in loss record 3 of 3
==19565==    at 0x4C2B6CD: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19565==    by 0x519D20A: __fopen_internal (iofopen.c:76)
==19565==    by 0x40112C: main (in /home/muniek/Desktop/c_code/a.out)
==19565==
==19565== LEAK SUMMARY:
==19565==    definitely lost: 0 bytes in 0 blocks
==19565==    indirectly lost: 0 bytes in 0 blocks
==19565==      possibly lost: 0 bytes in 0 blocks
==19565==    still reachable: 1,704 bytes in 3 blocks
==19565==         suppressed: 0 bytes in 0 blocks
==19565==
==19565== For counts of detected and suppressed errors, rerun with: -v
==19565== ERROR SUMMARY: 2664 errors from 5 contexts (suppressed: 2 from 2)

我知道MAXN功能有问题(我是对的吗?)。

void MAXN (double AMP, int ix, double DX, int *NST, double* ETE, int SP, double* C0, double* X0, double* CR, double* XC, int *N0, int *NC, double T,
  double *T0, int* GPC, double PER)
{
  double XCC, PFIX, TN;
  int SX0, ST, FN, N;

  ST = NINT((0.5/DX)+1);
  FN = NINT((1.0/DX)+1);

  PFIX = 3.0*PER/4.0;
  TN = T;
  SX0 = NINT((X0[*NST]/DX)+1);

  if (SX0 > SP+5)
    (*NST)++;

  //checks for new wave crests entering the computational domain
  for (int i = ST; i <= FN; i++)
  {
    if ((ETE[i] > ETE[i-1]) && (ETE[i] > ETE[i+1]) && (ETE[i] > 0) && (ETE[i] > (AMP/4.0)))
    {
      XCC = double((i-1)*DX);
      if ((XCC < (X0[*NC]-DX)) && ((TN-*T0) > PFIX))
      {
        *NC = *N0 + 1;
        XC[*NC] = XCC;
        CR[*NC] = ETE[i];
        *T0 =T;
         goto stop;
      }
    }
  }
  stop://label 2 continue

  //tracks existing wave crests within the computational domain
  for (int j = *NST; j <= *NC; j++)
  {
    N = NINT((X0[j]/DX)+1);
    int NCC = 0;

    for (int i = (N - 1); i <= (N + ST); i++)
    {
      if ((ETE[i] > ETE[i-1]) && (ETE[i] > ETE[i+1]) && (ETE[i] > 0))
      {
        NCC++;
        CR[j] = ETE[i];
        XC[j] = double((i-1)*DX);
      }

      if (NCC == 0)
      {
        for (int k = N-10; k <= N+10; k++)
        {
          if ((ETE[k] > ETE[k-1]) && (ETE[k] > ETE[k+1]) && (ETE[k] > 0))
          {
            CR[j] = ETE[k];
            XC[j] = double((k-1)*DX);
          }
        }
      }
    }
  }
  //update wave crests and position for next step
  for (int i = *NST; i <= *NC; i++)
  {
    GPC[i] = NINT((XC[i]/DX)+1);
    X0[i] = XC[i];
    C0[i] = CR[i];
  }

  *N0 = *NC;
}

如何更精确地获取导致段错误的代码位置?代码的哪一部分可以做到这一点?

2 个答案:

答案 0 :(得分:3)

使用调试支持编译代码并使用GDB运行代码。发生段错误时,您可以查看跟踪并查看错误发生的位置。

答案 1 :(得分:0)

您是否正在使用调试信息编译程序?通过使用-g选项运行gcc可以启用此功能。如果您的程序有调试信息,valgrind将告诉发生无效访问的行号。使用调试信息,您还可以更轻松地使用gdb。