3

extern "C" を使用して C++ で ARPACK 関数を宣言することにより、行列の固有ベクトルを見つけようとしています。

extern "C" {void znaupd_(int *IDO, char *BMAT, int *N, char *WHICH,
                 int *NEV, double *TOL, complex<double> *RESID,
             int *NCV, complex<double> *V, int *LDV,
             int *IPARAM, int *IPNTR, complex<double> *WORKD,
             complex<double> *WORKL, int *LWORKL, 
             double *RWORK, int *INFO);}

extern "C" {void zneupd_(bool *RVEC, char *HOWMNY, bool *SELECT, 
             complex<double> *D, complex<double> *Z,
             int *LDZ, complex<double> *WORKEV, 
             complex<double> *SIGMA, char *BMAT, int *N,
             char *WHICH, int *NEV, double *TOL, 
             complex<double> *RESID, int *NCV, 
             complex<double> *V, int *LDV, int *IPARAM,
             int *IPNTR, complex<double> *WORKD, 
             complex<double> *WORKL, int *LWORKL, int *INFO);}

次に、コードの本文で関数を呼び出します。

  do{
    znaupd_(&IDO, &BMAT, &N, WHICH, &NEV, &TOL, RESID, &NCV, V, &LDV, IPARAM,
        IPNTR, WORKD, WORKL, &LWORKL, RWORK, &INFO);
    switch(abs(IDO)){
    case - 1:
      for(i = 0; i < N; i++) X[i] = WORKD[IPNTR[1] + i];
      gmm::mult(SM, X, Y);
      for(i = 0; i < N; i++) WORKD[IPNTR[2] + i] = Y[i];
      break;
    case 1:
      for(i = 0; i < N; i++) X[i] = WORKD[IPNTR[1] + i]; 
      gmm::mult(SM, X, Y);
      for(i = 0; i < N; i++) 
    {WORKD[IPNTR[2] + i] = Y[i];
      WORKD[IPNTR[3] + i] = X[i];}
      break;
    case 2:
      for(i = 0; i < N; i++)
    WORKD[IPNTR[2] + i] = WORKD[IPNTR[1] + i];
      break;
    }
  }while(IDO != 99);
  std::cout << &INFO << std::endl;
  zneupd_(&RVEC, &HOWMNY, SELECT, D, Z, &LDZ, WORKEV, &SIGMA, &BMAT, &N,
      WHICH, &NEV, &TOL, RESID, &NCV, V, &LDV, IPARAM, IPNTR, WORKD,
      WORKL, &LWORKL, &INFO);

ただし、コンパイルして実行すると、プログラムはセグメンテーション違反を起こします。GDB でバックトレースを実行すると、&INFO によって zneupd_ に渡されるアドレスが 0x0 であることがわかります。これにより、zneupd_ がこの位置に新しい値を割り当てようとすると、segfault が発生します。ただし、次のフレームに移動して print &INFO を使用すると、INFO がレジスタ 0x28a27c に格納されていると表示されます。何らかの理由で、私のプログラムは INFO の場所を zneupd_ に正しく渡しません。さらに困惑しているのは、znaupd_ が &INFO を適切に受信でき、その場所の値に問題なくアクセスして変更できることです。ある関数が引数を適切に受け取ることができるのに、他の関数ができない理由を誰か教えてもらえますか?

4

1 に答える 1