1

私はAMESimと呼ばれるシミュレーションソフトウェアをCでプログラミングしていますが、2次元配列の管理について支援が必要です。

AMESimは、SimulinkやLabViewなどの他のシミュレーションソフトウェアと同様に機能し、スケッチと呼ばれる環境にいくつかのアイコンを配置し、それらをリンクして、実際のシステムをシミュレートします。アイコンの後ろにはC関数があります。これは私が書いている部分です(まあ、Fortranから更新しています)。このソフトウェアには、必要なときにさまざまなサブモデルを呼び出し、時間の経過を管理するインテグレーターが組み込まれているため、コードのその部分に直接アクセスすることはできません。

これらのサブモデルの1つで問題が発生しています。このサブモデルが存在しない油圧ポンプのモデルは完全に機能しますが、このモデルが接続されている場合、シミュレーションは一定時間後(シミュレーションの1.8 ...秒後)に突然停止します。時間、または約1970年から1980年のインテグレータからの呼び出しの後)。

このサブモデルは、2次元表面に適用されたレイノルズ方​​程式を使用してトライボロジーに対してかなりの計算を行います。この方程式は、グラフィカルインターフェイスを介してユーザーが決定し、パラメーターとして関数に渡される行列を使用してコードで表されます。これらに基づいて、動的配列を使用して、またはポインターへのポインターの配列を使用して行列を実装する必要があります(1つの行列と言いますが、実際には、整数型と浮動小数点のいくつかの行列があります。一次元配列のダース)。行列の次元はですが(L+Le)*M、一部の配列には次元が(L+Le)あり、他の配列には次元がありますM

問題が発生した後、以下に示す状態になるまで、コードの一部を段階的に無効にすることで、エラーの考えられる原因を絞り込もうとしました。さまざまなテストを行って、問題は行列/配列の割り当てにあることを理解しました。ある瞬間に、行列の1つの行を割り当てようとするとmalloc、エラー(a)が返されます。NULL割り当て/割り当て解除を制御する関数とサブ関数のさまざまな構成を試しましたが、エラーが発生します。これは、コンパイラを変更するときにも発生します(IntelおよびMS VisualC 32ビットで試しました)。

コードは次のとおりです。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "ameutils.h"    //it is a library of AMESim that has various I/O utilities
#include <malloc.h>
#include <string.h>
#include <direct.h>
#include <errno.h>

//various functions prototypes
void allocate_matrix(int ***table, int rows, int columns) ;
void free_matrix(int*** table, int rows);
void allocate_matrixd(double ***table, int rows, int columns) ;
void free_matrixd(double*** table, int rows);

//bla bla check of parameters and so on

//this is my main function
void barreldin27wpprova_( \*bla bla, there are a lot of parameters 
for the calculation that I will skip */ , 
double *rp, //array with real parameters chosen by the user
int *ip, //array with integer parameters
double *c, //array with static double that are saved between calls of the function
int ic[6] //array with static int
) 
{

int loop, i;
double *Xdib=NULL, *Xwib=NULL, *Xddb=NULL, *Xwdb=NULL;
double **MatH=NULL, **MatPdim=NULL, **Matx=NULL, **Maty=NULL, **DummyMat=NULL, **MatZp=NULL;
int **DummyMatInt=NULL, **Matrixt=NULL, **Matrixtn=NULL, **Matrixp=NULL, **Matrixpn=NULL;
double *VectR=NULL, *DummyL=NULL, *DummyM=NULL, *tetar=NULL, *tetag=NULL, *radim=NULL;
//these are all of my arrays

//allocation of dynamic blocks
   allocate_matrix(&DummyMatInt,(L+Le),M);
      //repeat for all int matrices
   allocate_matrixd(&Matx,(L+Le),M);
      //repeat for all double matrices

//the program stops with an error from malloc during one of these allocations

   VectR= malloc((L+Le) * sizeof(double));
   if (VectR == NULL) { 
    amefprintf(stdout,"Error in allocation of VectR\n");   //amefprintf is internal
                            of AMESim, the same as fprintf
    AmeExit(1); //exit function of AMESim
    }
   //repeated for all dynamic arrays, then initialized to 0.e0 with "for" cycles

//a lot of calculation and subfunctions, that are all disabled in this example; function outputs 
  are set to zero

//Deallocation of dynamic blocks
free_matrix(&DummyMatInt, (L+Le));    //repeated for all int matrices
free_matrixd(&Matx, (L+Le));          //repeated for all double matrices
free(VectR); VectR =NULL;             //repeated for all arrays
}

これらは、割り当て/割り当て解除の2つの関数です。スペース上の理由から、整数の関数のみを記述します。

void allocate_matrix(int ***table, int rows, int columns) 
{
 int i,j;

 *table =  malloc(rows * sizeof **table );
  if (*table == NULL) { 
    amefprintf(stdout,"Error in memory allocation array of pointers\n");
    AmeExit(1);
    }

 for (i = 0; i < rows; i++) {
     (*table)[i] = malloc(columns * sizeof *(*table)[i]);
     if ((*table)[i] == NULL) { 
        amefprintf(stdout,"Error in memory allocation row %d \n",i);
        AmeExit(1);
        }
     for (j=0; j < columns; j++) {
        (*table)[i][j] = 0;
     }
    }

 }   

void free_matrix(int*** table, int rows)
{
int i;
for (i = 0; i < rows; i++)
    {
    free ((*table)[i]);
    (*table)[i] = NULL;
    }
free (*table);
*table = NULL;
return;
}

ポインタのすべての参照/逆参照で何かを台無しにしたかどうかを確認し、ヒープの空き領域を制御する方法をよりよく理解するために書いていました。エラーのもう1つの説明(最後のリソースとして考慮に入れる必要があると思います)は、ソフトウェアインテグレーターに未知のバグがあることですが、検証するのは確かに困難です。

4

1 に答える 1

0

Leパラメータが正しく初期化されていないことが判明しました(配列の割り当て後に初期化されました)。

したがって、割り当て中はカジュアルな値(たとえば)があり、メモリブロック20のスペースが割り当てられましたが、初期化されたときの値はでした。が呼び出されると、メモリブロックのみが解放され、プログラムの長時間の実行中にメモリリークが発生しました。L+200freeL+0

残念ながら、AMESimの構造は、特にパラメーターの割り当てに関しては少し複雑です。また、Fortranはこの種のエラー(または単にそれらをスキップする)、IMOの傾向が少ないため、一方から他方への変換中に、この種の混乱がすべて発生します...

読んだり返信したりしてくれた人たちに感謝します!

于 2012-10-23T08:10:49.347 に答える