释放函数中的malloced结构

时间:2015-10-01 09:47:02

标签: c pointers malloc free

我正在创建一个包含缓冲区功能的源文件,我希望将其用于我正在创建的其他库中。

它工作正常,但我无法摆脱我在其中一个功能中创建的缓冲区结构。以下片段应该有助于说明我的问题:

C标题:

//dbuffer.h
...

typedef struct{
    char *pStorage;
    int *pPosition;
    int next_position;
    int number_of_strings;
    int total_size;
    }DBUFF; 
...

C来源:

//dbuffer.c
...
DBUFF* dbuffer_init(char *init_pArray)
    {
    //Find out how many elements the array contains
    int size = sizeof_pArray(init_pArray);                         

    //Initialize buffer structure
    DBUFF *buffer = malloc(sizeof(DBUFF));                                       

    //Initialize the storage
    buffer->pStorage = malloc( (sizeof(char)) * (size) );

    strncpy( &(buffer->pStorage)[0] ,  &init_pArray[0] , size);
    buffer->number_of_strings = 1;

    buffer->total_size = size;
    buffer->next_position = size; //size is the next position because array allocates elements from 0 to (size-1)

    //Initialize the position tracker which keeps record of starting position for each string
    buffer->pPosition = malloc(sizeof(int) * buffer->number_of_strings );
    *(buffer->pPosition + (buffer->number_of_strings -1) ) = 0;

    return buffer;
    }

void dbuffer_destroy(DBUFF *buffer)
    {
    free(buffer->pStorage);
    free(buffer);
    }
...

主要:

#include <stdio.h>
#include <stdlib.h>
#include "dbuffer.h"


int main(int argc, char** argv)
    {
    DBUFF *buff; 

    buff = dbuffer_init("Bring the action");
    dbuffer_add(buff, "Bring the apostles");
    printf("BUFFER CONTENTS: ");
    dbuffer_print(buff); 

    dbuffer_destroy(buff);

    // Looks like it has been succesfully freed because output is garbage
    printf("%s\n", buff->pStorage);   

    //Why am I still able to access struct contents after the pointer has been freed ?
    printf("buff total size: %d\n", buff->total_size);

    return (EXIT_SUCCESS);
    }

输出:

BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36

RUN SUCCESSFUL (total time: 94ms)

问题:

为什么在释放指向结构的指针后,我仍然可以使用下面的行访问struct内容?

printf("buff total size: %d\n", buff->total_size);

4 个答案:

答案 0 :(得分:7)

在分配的指针上调用free()后,尝试使用指针调用undefined behavior。你不应该这样做。

引用C11标准,章节§7.22.3.4, free()函数

  

free()函数导致ptr指向的空间被释放,即   可供进一步分配。 [..]

它永远都不会说 cleanup ,你可能(错误地)期待它。

为了增加清晰度,调用free()并不总是释放分配的物理内存。它只是允许再次分配指针(内存空间)(例如返回相同的指针),以便连续调用malloc()和family。在调用free()之后,该指针不再用于您的程序,但C标准不保证已分配内存的清理

答案 1 :(得分:6)

如果尝试读取已free的内存,则可能导致程序崩溃。或者他们可能不会。就语言而言,其 未定义的行为

您的编译器不会警告您(或阻止您访问它)。但是在致电free -

之后,显然不会这样做
printf("buff total size: %d\n", buff->total_size);

作为一种良好做法,您可以将free d指针设置为NULL

答案 2 :(得分:3)

free()调用只会标记堆中的内存可供使用。所以你仍然有指针指向这个内存位置,但它不再适用于你。因此,对malloc()的下一次调用可能会将此内存分配给新的预留。

通常,一旦释放()分配给指针的内存,就应该将其设置为NULL。取消引用NULL也是UB,但至少在调试时你可以看到不应该使用指针,因为它没有指向有效的内存地址。

答案 3 :(得分:2)

[评论太久了]

允许你的&#34;析构函数&#34;设置传递给NULL的指针修改你的代码如下:

void dbuffer_destroy(DBUFF ** buffer)
{
  if ((NULL == buffer) || (NULL == *buffer))
  {
     return;
  }

  free((*buffer)->pPosition);
  free((*buffer)->pStorage);
  free(*buffer);
  *buffer = NULL;
}

并将其称为:

  ...
  dbuffer_destroy(&buff);
  ...