微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在C中使用动态分配的内存

如何解决如何在C中使用动态分配的内存

我一直在使用C语言在Scilab / Xcos(Matlab / Simulink的开源变体)中开发一个模块。为此,Scilab / Xcos提供了一个称为CBLOCK4的特殊块。一旦将此块放入仿真中,就会自动生成一个C语言存根。该存根的一部分是用于实现该块行为的功能的模板。此函数在其参数中接受指向scicos_block结构的指针:

typedef struct {
  int nevprt;
  voidg funpt ;
  int type;
  int scsptr;
  int nz;
  double *z;
  int noz;
  int *ozsz;
  int *oztyp;
  void **ozptr;
  int nx;
  double *x;
  double *xd;
  double *res;
  int nin;
  int *insz;
  void **inptr;
  int nout;
  int *outsz;
  void **outptr;
  int nevout;
  double *evout;
  int nrpar;
  double *rpar;
  int nipar;
  int *ipar;
  int nopar;
  int *oparsz;
  int *opartyp;
  void **oparptr;
  int ng;
  double *g;
  int ztyp;
  int *jroot;
  char *label;
  void **work;
  int nmode;
  int *mode;
} scicos_block;

项目work可能旨在用于存储另一个地址的地址,在另一个地址存储的是块的内部状态变量。我尝试使用work项目用法来实现Scilab / Xcos块:

#include "scicos_block4.h"

#define U  ((double *)GetRealInPortPtrs(block,1))
#define Y  ((double *)GetRealOutPortPtrs(block,1))

// parameters
#define Tu (GetRparPtrs(block)[0])
#define Td (GetRparPtrs(block)[1])
#define T  (GetRparPtrs(block)[2])


void Ramp(scicos_block *block,int flag)
{
 
  double *target;
  double *inputDelta;
  double *out;

  if(flag == 4) 
  {
    /* init */
    if((*(block->work) = (double *)scicos_malloc(sizeof(double)*3)) == NULL)
    {
        set_block_error(-16);
        return;
    }
        
    target      = (double*)(*(block->work));
    inputDelta  = (double*)(*(block->work + 1));
    out         = (double*)(*(block->work + 2));

    *target     = 0;
    *inputDelta = 0;
    *out        = 0; 

  }
  else if(flag == 1) 
  {
    /* output computation */ 
    if(U[0] != *target)
    {
        *target = U[0];
        
        if(*target - Y[0] < 0)
        {
            *inputDelta = Y[0] - *target;
        }
        else
        {
            *inputDelta = *target - Y[0];
        }
    }
    
    if(*target > Y[0])
    {
        *out += *inputDelta*T/Tu;
        if(*out > *target)
        {
            *out = *target;
        }
    }
    else if(*target < Y[0])
    {
        *out -= *inputDelta*T/Td;
        if(*out < *target)
        {
            *out = *target;
        }
    }
    
    Y[0] = *out;  
  } 
  else  if (flag == 5) 
  {
    /* ending */
    scicos_free(*(block->work));

  }

}

我能够成功地编译包含此代码的块,但是如果我开始仿真,它将崩溃。我对内存的动态分配及其使用方式有疑问。

请任何人看看我的代码(即if主体中带有flag == 4的部分),然后告诉我我在做什么错吗?

解决方法

此行

target      = (double*)(*(block->work));

是正确的,但这些行

inputDelta  = (double*)(*(block->work + 1));
out         = (double*)(*(block->work + 2));

错了。

(*(block->work)将为您提供三个malloc的双打中的第一个的指针。

但是,您不会像以前那样获得下一个加倍-您添加得太早了。像这样更改它:

(double*)(*(block->work + 1));   // Wrong !!
(double*)(*(block->work)) + 1;   // Correct !!
^^^^^^^^^^^^^^^^^^^^^^^^^   ^
Get pointer to malloced     Then add 1 to get to the second malloc'ed double
memory (i.e. the first
malloc'ed double) and use 
it as a double-pointer

或者只是这样做:

target      = (double*)(*(block->work));
inputDelta  = target + 1;
out         = target + 2;

顺便说一句:您不需要所有的转换。只需将其删除。

编辑:在评论中,OP告知它仍然崩溃

发布的代码未告诉我们block->work在调用Ramp之前是否已初始化。如果尚未进行过初始化,则进行*(block->work)是非法的-可能会导致崩溃。

所以也许代码缺少诸如以下内容:

/* init */
block->work = malloc(sizeof *block->work);  // Add this line
if((*(block->work) = (double *)scicos_malloc(sizeof(double)*3)) == NULL)
,

如用户4386427answer中所述,(double*)(*(block->work + 1))应该为(double*)(*(block->work)) + 1。如果sizeof(double)sizeof(void*)具有不同的值,这尤其重要。 (在典型的64位系统上,它们将具有相同的值,但是在典型的32位系统上,它们将具有不同的值。)

另一个严重的问题是,当flag == 1targetinputDeltaout变量包含未初始化的值但被取消引用时。必须先在else if (flag == 1)块中分配变量,然后才能使用与if (flag == 4)块中相同的方式取消引用。

我认为,如果定义了struct类型来保存工作数据,代码将会更简洁:

struct Ramp_work
{
    double target;
    double inputDelta;
    double out;
};

void Ramp(scicos_block *block,int flag)
{
    struct Ramp_work *work;

    if (flag == 4)
    {
        /* init */
        work = scicos_malloc(sizeof(*work));
        *block->work = work;
        if (work == NULL)
        {
            set_block_error(-16);
            return;
        }
        work->target = 0;
        work->inputDelta = 0;
        work->out = 0;
    }
    else if (flag == 1)
    {
        /* output computation */
        work = *block->work;
        if (U[0] != work->target)
        {
             /* etc. */
        }
        /* etc. */
    }
    else if (flag == 5)
    {
        /* ending */
        scicos_free(*block->work);
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。