1

我正在使用 ANSI C 代码,它是从代码生成器生成的,该代码生成器生成多层嵌套struct以及带有参数列表的函数原型,这些参数列表使用指向顶层的指针来struct传递或访问位于内部 mmost 中的数据struct

因为函数原型将指针传递给 struct,所以应用程序必须分配内存来访问或向最内部的 struct 成员写入数据。我在尝试为指向第二个嵌套结构的指针分配内存时看到了问题。

我得到的实际错误消息是非致命的运行时:“没有足够的空间将表达式转换为'指向结构数据的指针'。”

我没有明确地投射任何东西,所以我怀疑 的实现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()关联的内存b,这是一个具有自动存储持续时间的结构。您只能free()动态分配内存。

  3. 你有一个奇怪的评论allocate(),“这只是一个指针,它不应该只分配 4 个字节并继续吗?”。如果您在具有 32 位指针的系统上,那么这确实是您分配的,但是在 32 位机器上看起来它需要 28 个字节c->pData的指针,所以您应该为struct data它。像这样的行c->pData->wsDate = ...似乎表明你很清楚它是一个指向 a 的指针struct data,所以真的不清楚为什么你认为你应该只分配 4 个字节。当您为 anANYTHING *指向的内存分配内存时,您需要为 an 分配足够的内存ANYTHING,而不是为 an分配足够的内存ANYTHING *,即为它要指向的东西分配足够的内存. 您首先尝试将内存分配给指针的事实证明您已经拥有指针的内存,否则您将无法做到这一点(前提是您之前没有搞砸分配,当然)。

  4. 你从不检查malloc()and的返回calloc(),你应该检查。

  5. 以双下划线开头的名称始终保留用于实现,因此您应该调用__sizeM_Details其他名称。

  6. sizeof(char)根据定义为 1,因此永远不需要使用它。

  7. 目前尚不清楚您为什么要为您的 分配内存numRecords + 1struct details而不是numRecords看起来很直观。也许您希望将最后一个设置NULL为哨兵值,但如果您已经在结构中存储了记录数,那么这并不是必需的。

这是您的代码应如下所示:

#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 回答