1

私は ANSI C コードを使用しています。これは、ネストされたいくつかのレイヤーとstruct関数プロトタイプを生成するコード ジェネレーターから生成され、引数リストを使用して最上位レイヤーへのポインターを使用structして、内部 mmost にあるデータを渡したりアクセスしたりしますstruct

関数プロトタイプはポインターを構造体に渡すため、アプリケーションは最も内側の構造体メンバーにアクセスまたはデータを書き込むためにメモリを割り当てる必要があります。2 番目のネストされた構造体へのポインタにメモリを割り当てようとすると、問題が発生します。

実際に表示されるエラー メッセージは、致命的ではないランタイム メッセージです。

私は明示的に何もキャストしていないので、の実装にmalloc()は、何らかの条件が発生したときにメッセージを生成するアサートがあると思われます。このエラーの文言は、私の環境 (私は LabWindows/CVI を使用しています) に固有のものかもしれませんが、他の ANSI C コンパイラの結果も知りたいです。

これは、コンパイル、ビルド、および実行する必要がある単純化された完全なコード スニペットです (インラインでコメントされているエラーの場所まで)。

エラーの原因についてのコメントと、それを修正する方法についての提案をいただければ幸いです。

#include <ansi_c.h> //specific to LabWindows/CVI - change as needed for your environment

struct request
{
    struct data *pData; 
};

struct data
{
    char *wsDate;   
    char *wsDuration;
    char *wsFailures;
    int __sizeM_Details;    
    struct details *M_Details;
};


struct details
{
    char *wsStep;   
    char *wsTestDesc;   
    char *wsLowLim; 
};

typedef struct request REQUEST;  // from mtdf function prototype request argument (4)
typedef struct details DETAILS; // member of REQUEST - _ns1__MTDFData_MTDFDetail  

void allocate(REQUEST *a, int numRecords);
void freemem(REQUEST *c, int numRecords);

int main(void)
{
    REQUEST b, *pB;

    pB = &b;

    allocate(pB, 10);
    freemem(pB, 10);
    return 0;   
}

void allocate(REQUEST *c, int numRecords)
{
    DETAILS m_Param;
    REQUEST b;
    struct data d;

    size_t size_c = sizeof(c);
    c = malloc(size_c); //4 bytes

    size_t size_c_data = sizeof(c->pData);
    c->pData = malloc(size_c_data);  //Breaks here - this is just a pointer, 
                                     //should it not just allocate 4 bytes
                                     //and continue?
    //  Actual error message: 
    //  "Not enough space for casting expression to 'pointer to struct data'."
    c->pData->wsDate = calloc(80, sizeof(char));

    c->pData->__sizeM_Details = numRecords;
    c->pData->M_Details = calloc((numRecords + 1) , sizeof(m_Param)); 

}

void freemem(REQUEST *c, int numRecords)
{
    free(c->pData->M_Details);
    free(c->pData->wsDate);
    free(c->pData);
    free(c);
}
4

1 に答える 1

3

ここにはいくつかの基本的な問題があります。

  1. ではallocate()、使用しているすべてのメモリが関数の最後で失われます。これは、関数の最後で破棄さmalloc()れるローカル変数に割り当てているためです。c関数に渡す自動ストレージ期間で構造体のアドレスを使用することはありません。オブジェクトのアドレスを自動保存期間で渡す場合は、malloc()明らかに既にメモリを持っているため、構造体自体ではなく、メンバーのメモリを確保する必要があります。

  2. 次に、 に関連付けられたメモリにfreemem()アクセスしようとします。これは、自動保存期間を持つ構造体です。動的に割り当てたメモリのみを使用できます。free()bfree()

  3. allocate()に、「これは単なるポインターです。4 バイトを割り当てて続行するべきではありませんか?」という興味深いコメントがあります。32 ビット ポインターを使用するシステムを使用している場合、それは実際に割り当てたものですが、32 ビット マシンでは 28 バイトが必要なように見えるc->pDataポインターでstruct dataあるため、4 バイトよりも多くを割り当てる必要があります。それ。のような行c->pData->wsDate = ...は、それが へのポインタであることを十分に認識していることを示しているように見えるため、struct data4 バイトのみを割り当てる必要があると考える理由がよくわかりません。が指し示すメモリを割り当てる場合、ではなく にANYTHING *十分なメモリを割り当てる必要があります。つまり、 が指すものに十分なメモリを割り当てる必要があります。ANYTHINGANYTHING *. そもそもポインタにメモリを割り当てようとしているという事実は、ポインタ用のメモリが既にあることを証明しています。もちろん割り当て)。

  4. malloc()とからの戻り値をチェックすることはありません。チェックするcalloc()必要があります。

  5. 2 つのアンダースコアで始まる名前は常に実装用に予約されているため、別の__sizeM_Detailsものを呼び出す必要があります。

  6. sizeof(char)は定義上 1 であるため、使用する必要はありません。

  7. 直感的に見えるのではなく、numRecords + 1メモリをメモリに割り当てている理由は不明です。最後の値をセンチネル値として設定しようとしているのかもしれませんが、構造体にレコード数を既に格納している場合、これは実際には必要ありません。struct detailsnumRecordsNULL

コードは次のようになります。

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

struct request {
    struct data * pData; 
};

struct data {
    char * wsDate;   
    char * wsDuration;
    char * wsFailures;
    int sizeM_Details;    
    struct details * M_Details;
};

struct details {
    char * wsStep;   
    char * wsTestDesc;   
    char * wsLowLim; 
};

typedef struct request REQUEST;
typedef struct details DETAILS;

void allocate(REQUEST * c, const int numRecords);
void freemem(REQUEST * c);

int main(void)
{
    REQUEST b;
    allocate(&b, 10);
    freemem(&b);
    return 0;   
}

void allocate(REQUEST * c, const int numRecords)
{
    if ( !(c->pData = malloc(sizeof *c->pData)) ) {
        perror("couldn't allocate memory for c->pData");
        exit(EXIT_FAILURE);
    }

    if ( !(c->pData->wsDate = calloc(80, 1)) ) {    
        perror("couldn't allocate memory for c->pData->wsDate");
        exit(EXIT_FAILURE);
    }

    if ( !(c->pData->M_Details = calloc(numRecords + 1,
                                        sizeof(*c->pData->M_Details))) ) {
        perror("couldn't allocate memory for c->pData->M_Details");
        exit(EXIT_FAILURE);
    }

    c->pData->sizeM_Details = numRecords;
}

void freemem(REQUEST * c)
{
    free(c->pData->M_Details);
    free(c->pData->wsDate);
    free(c->pData);
}

への自動ストレージの割り当てbが間違いであり、 を含むすべてを動的に割り当てたい場合はstruct request、次のようになります。

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

struct request {
    struct data * pData; 
};

struct data {
    char * wsDate;   
    char * wsDuration;
    char * wsFailures;
    int sizeM_Details;    
    struct details * M_Details;
};

struct details {
    char * wsStep;   
    char * wsTestDesc;   
    char * wsLowLim; 
};

typedef struct request REQUEST;
typedef struct details DETAILS;

REQUEST * allocate(const int numRecords);
void freemem(REQUEST * c);

int main(void)
{
    REQUEST * b = allocate(10);
    freemem(b);
    return 0;   
}

REQUEST * allocate(const int numRecords)
{
    REQUEST * c = malloc(sizeof *c);
    if ( !c ) {
        perror("couldn't allocate memory for c");
        exit(EXIT_FAILURE);
    }

    if ( !(c->pData = malloc(sizeof *c->pData)) ) {
        perror("couldn't allocate memory for c->pData");
        exit(EXIT_FAILURE);
    }

    if ( !(c->pData->wsDate = calloc(80, 1)) ) { 
        perror("couldn't allocate memory for c->pData->wsDate");
        exit(EXIT_FAILURE);
    }

    if ( !(c->pData->M_Details = calloc(numRecords + 1,
                                        sizeof(*c->pData->M_Details))) ) {
        perror("couldn't allocate memory for c->pData->M_Details");
        exit(EXIT_FAILURE);
    }

    c->pData->sizeM_Details = numRecords;

    return c;
}

void freemem(REQUEST * c)
{
    free(c->pData->M_Details);
    free(c->pData->wsDate);
    free(c->pData);
    free(c);
}
于 2014-10-06T23:34:53.483 に答える