ANSI C指向struct的指针的内存分配会引发非致命的运行时错误

时间:2014-10-06 22:20:33

标签: c struct malloc ansi labwindows

我使用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);
}

1 个答案:

答案 0 :(得分:3)

这里有几个基本问​​题:

  1. allocate()中,您malloc()的所有内存都会在函数结束时丢失,因为您将其分配给局部变量{{1} },在你的函数结束时被破坏。您永远不会使用传递给函数的自动存储持续时间的结构地址。如果你传递一个具有自动存储持续时间的对象的地址,那么你应该c成员的内存,而不是结构本身,因为它显然已经有了内存。

  2. 然后,在malloc()中,您尝试freemem()free()关联的内存,这是一个具有自动存储持续时间的结构。您只能动态分配b个内存。

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

  4. 您永远不会检查ANYTHING *malloc()的回复,您应该这样做。

  5. 以双下划线开头的名称始终保留给实现,因此您应该调用calloc()其他内容。

  6. 根据定义,
  7. __sizeM_Details为1,因此无需使用它。

  8. 目前还不清楚为什么要为sizeof(char)的{​​{1}}分配内存,而不仅仅是numRecords + 1,这看起来很直观。也许您希望将最后一个设置为struct details作为标记值,​​但如果您已经在结构中存储了记录数,那么这不是必需的。

  9. 以下是您的代码应该是什么样的:

    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