什么时候需要在指针上使用malloc分配动态内存?

时间:2013-06-20 16:34:43

标签: c pointers malloc

我无法完全理解C中的malloc()函数,更准确地说是在需要使用它时。

当我声明一个指向全局结构的指针时,

struct Position* currentPositionPtr;

我是否需要使用malloc为其分配动态内存来初始化它? 或者,稍后在需要时简单地将结构的指针指定给它是一种好的做法,例如,

currentPositionPtr = getPosition();

其中getPosition()返回指向“struct Position”的指针。

6 个答案:

答案 0 :(得分:8)

getPosition()做了什么?

如果它返回一个指向struct Position的有效指针,那么你当然不需要为struct 分配两次内存。我希望你的函数看起来像这样:

struct Position *getPosition()
{
    struct Position p = { x, y };
    return &p;
}

因为这会显示未定义的行为(通过返回指向块作用域自动对象的指针)。通常,您宁愿返回已经 malloc()指针:

struct Position *getPosition()
{
    struct Position *p = malloc(sizeof(*p));
    p->x = 42;
    p->y = 1337;
    return p;
}

然后,再次,您不需要对malloc()进行其他来电。

但是,如果不是被叫函数负责分配,那么,那么......是调用者:

void getPosition(struct Position *p)
{
    p->x = 42;
    p->y = 1337;
}

在后一种情况下,您需要像这样调用它:

struct Position *p = malloc(sizeof(*p));
getPosition(p);

如果你需要你的结构来恢复功能,或者

struct Position p;
getPosition(&p);

如果你没有。

答案 1 :(得分:2)

只要您需要系统为您提供内存,就需要

malloc(或其他内存分配函数)。

是的,当你做的时候

struct Position* currentPositionPtr;

您需要致电malloc()

currentPositionPtr = malloc(sizeof(struct Position));

或将指针指定给已分配的内存块的地址:

struct Position globalPos;

void func(void) {
    struct Position pos;
    struct Position* currentPositionPtr = &pos; //ok
    struct Position* globalPosPtr = &globalPos; //also ok
    ...
}

因为您所做的只是声明指针,而不是为结构保留空间。

但是,如果指针是全局,则将其分配给堆栈分配的内存可能会有危险。请考虑以下事项:

struct Position *globalPosPtr = NULL;

void foo(void) {
    struct Position pos;
    globalPosPtr = &pos;
    //can dereference globalPosPtr with no problems here
    ...
}

void bar(void) {
    foo();
    //globalPosPtr is invalid here
    ...
}

关于你有另一个返回指针的函数的问题:

getPosition()需要使用malloc或其他一些内存分配函数。所以这样做非常好,如果您通常希望将结构中的值初始化为某些值,则可以理解。但是,请记住,即使您在其他函数中调用了malloc,当您使用它以防止内存泄漏时,您需要free内存。

要回答标题中的问题,无论何时将某些内容声明为指针,如果要使用它,都需要指出一些内容。如果您希望它指向一个新事物,您需要使用malloc()或相关函数动态分配它。

答案 2 :(得分:1)

通常,在这些情况下使用malloc

  1. 当你想动态分配内存时换句话说,当你不知道你需要多少内存时。或者当你不知道什么时候你不再需要它时。
  2. 当您想分配大量内存时:堆可能会变得非常大,但堆栈受到的限制更多。在堆栈上分配非常大的东西可能会导致堆栈溢出(嘿!这就是站点的名称!)。当然,这样的大小是特定于实现的,因此相当主观的短语“非常大”。
  3. 如果希望分配的内存可以从外部访问:如果程序的其他线程需要访问一块内存,那么在一个线程的堆栈上分配它将是一个坏主意,因为它可以在该线程移动时被覆盖,然后其他所有人都会看到损坏的内存。
  4. 可能还有其他一些案例。

答案 3 :(得分:0)

好像你已经知道malloc是如何工作的,但我会试着回答你的问题。

每当你使用malloc时,只要确保在它上面放一个指针,这样你就可以操纵它(或释放它)。 malloc的优点在于它是动态的。您可以声明malloc的结构的链接列表(例如),而不是声明一个数组,并使用指针来跟踪它们。通过这种方式,您永远不会遇到诸如走出阵列之类的问题。相反,您可以动态地请求更多空间,并在以后需要时释放它。

答案 4 :(得分:0)

如果您使用的是已知大小的结构,则不必使用malloc来分配内存,因为内存在不同的struct Position之间不可更改,但是,

如果在struct Position中,你有一个指向未知大小的指针,这取决于一些用户输入,那么你可以使用malloc来分配所需内存块的大小。

如果要分配struct Position数组,那么

currentPositionPtr = malloc(sizeof(struct Position)*neededSize);

完成后,您必须使用

删除内存
free (currentPositionPtr)

答案 5 :(得分:0)

很难理解:

  1. malloc()只是从堆返回内存,用户进程负责通过调用FREE系统调用来释放这块内存。

  2. 当您在编码时知道,您需要处理固定数量的内存时,请说一个结构,一个数组,然后您可以使用局部变量和全局变量来满足进程的内存需求。

  3. 从您的查询中,当您必须处理malloc并作为结果指针时,您似乎感到困惑。

    1. 您需要一个指针来保存malloc系统调用分配的内存地址。
    2. 指针不一定指向malloc分配的内存,它可以是任何有效的内存,如:

       int a =2;
       int *ptr; 
       ptr = &a;
      
    3. 所以在这里,ptr指向内存位置未由malloc分配。

      相反,你可以做到

         int *ptr;  
         ptr = (int*)malloc(sizeof(int));
      

      在你的情况下,指针currentPositionPtr to struct可以指向全局/局部变量的地址,前提是内存地址在整个访问此指针时仍然有效。

      我希望这会简化事情。