以下内存分配有什么不同吗?

时间:2009-08-07 03:08:38

标签: c memory memory-management pointers malloc

动态分配内存有四种方法,这四种方式有区别吗? 首先是这样的:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    // using 'seq'
}

第二个像这样:

char *seq;
void exam(char *seq){
    seq=(char *)malloc(100*sizeof(char));
    // using 'seq'
}

第三个​​像这样:

char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
    char *change=(char *)malloc(100*sizeof(char));
    free(seq);
    seq=change;
    // using 'seq'
}

第四个像这样:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    free(seq);
    seq=(char *)malloc(100*sizeof(char));
    //using 'seq'
}

你应该知道,我会在方法'考试'之外使用变量'seq'。 请解释上述代码,非常感谢。

6 个答案:

答案 0 :(得分:2)

如果您打算在考试之外使用seq,则只有第一种情况有效。

其他三种情况接收为seq分配的地址,但无法更改。

要更改seq的值,您需要为其返回一个新值,或者显式修改seq中的内容。

您需要调查Pass by Value以了解为什么这不起作用。请参阅this page

答案 1 :(得分:1)

这一切都取决于你想要做什么。如果可能的话,最好在相同的范围内进行malloc / free,IMO,它使代码更具可读性 - C中的内存分配已经足够困难了。在您的情况下,您将首先malloc,调用该函数,并在函数外部释放。但当然,并非总是可行。

你的一些解决方案不起作用:例如,第二个解决方案不会做你想要的,因为当你调用函数时,指针被复制

char *p;
function(p);

void function(char *q) {
    // q is a copy of p, so when q is set by malloc, it will not be reflected in p
    q = malloc(100);
}

通常,你应该做fopen函数:你返回一个指针:

char* p function() {
    char* ret;
    ret = malloc(100);
    return ret;
}

char *p = function();

或者您可以使用指向指针的指针:

char *p;
function(&p);

void function(char **q) {
    // q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
    *q = malloc(100);
}

我认为第一个一般情况要好得多。

另外,关于你的风格:sizeof(char)是无用的,无论你使用什么编译器/平台,它总是等于1,并且转换malloc是无用的并且实际上是危险的(因为它隐藏了缺少的头部包含在哪里malloc被声明)。只有在C ++中使用malloc时才有用(强制转换为强制转换)。

答案 2 :(得分:1)

可能有很多方法可以做你做的事情。如果您打算在函数外部使用seq,那么您概述的第一种方法将起作用。

如果您打算在调用函数后使用seq,那么其他方法还有其他问题。由于C是按值传递的,因此您将seq中包含的地址传递给例程,该例程不会更改最后三个示例中与seq关联的内存位置。要更改seq的内存位置,需要将指针的地址传递给例程以设置指针。这在David Cournapeau的例子中有所体现。

最后两种情况的问题是你“释放”了内存,但你仍然保留了一个指向内存的指针,因为seq的值不会被改变,你可以使用它来访问你已经“释放”的内存”。这是一个悬垂的指针。

David Cournapeau建议使用函数返回指针,这样您就可以访问在函数中分配的内存。否则,您需要将seq的地址传递给例程,并取消引用该值以将其设置为已分配的空间。

答案 3 :(得分:1)

你不应该转换malloc()的结果,除非你使用的是早于1989 ANSI标准的C实现,或者你打算用C ++编译这个代码,在这种情况下你应该使用new而不是malloc ();首先,它没有必要,其次,如果你没有范围内的malloc()原型,它将掩盖编译器诊断。

另外,sizeof(char)的定义是1;在这种情况下使用它没有任何区别,只是增加了视觉噪音。

为任何类型T编写malloc()语句的规范形式是

T *p = malloc(count * sizeof *p);

T *p;
...
p = malloc(count * sizeof *p);

现在处理你的四个案件......

你的第一个案件通常是正确的;你在考试之外为seq分配内存,并按值传递指针。

你剩下的案件都有类似的问题;对指针值seq的更改不会反映在调用者中,并且您将引入内存泄漏。如果您正在传递指向函数的指针,并且希望覆盖指针值,则需要将指针传递给该指针:

char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }

如果要调整动态分配的缓冲区的大小,请使用realloc():

char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq) 
{
  char *tmp = realloc(*seq, 100);
  if (!tmp) 
  {
    /* realloc failed */
  }
  else
  {
    *seq = tmp;
    ...
  }

请注意

char *p = realloc(NULL, 10);

相同
char *p = malloc(10);

答案 4 :(得分:0)

我认为这些是范围上的差异

答案 5 :(得分:0)

要了解情况,请考虑重写:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    // using 'var'
}
//--
char *seq;
void exam(char *var){
    var=(char *)malloc(100*sizeof(char));
    // using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
    char *change=(char *)malloc(100*sizeof(char));
    free(var);
    var=change;
    // using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    free(var);
    var=(char *)malloc(100*sizeof(char));
    //using 'var'
}

致电时

exam(seq);

以上版本与原版相同。