释放函数中的错位结构



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

它工作正常,但我有麻烦摆脱我在一个函数中创建的缓冲结构。下面的代码片段应该有助于说明我的问题:

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("%sn", buff->pStorage);   
    //Why am I still able to access struct contents after the pointer has been freed ?
    printf("buff total size: %dn", buff->total_size);
    return (EXIT_SUCCESS);
    }
输出:

BUFFER CONTENTS: Bring the action/0Bring the apostles/0
��/�
buff total size: 36
RUN SUCCESSFUL (total time: 94ms)

问题:

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

printf("buff total size: %dn", buff->total_size);

在分配的指针上调用free()后,尝试使用该指针调用未定义行为。你不应该那样做。

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

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

它从来没有说过任何关于清理的事情,这可能是你(错误地)期望的。

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

如果试图读取已被 freed的内存,可能会导致程序崩溃。也可能不会。就语言而言,它的未定义行为

编译器不会警告你(或阻止你访问)。但很明显,在调用free -

之后不要这样做
printf("buff total size: %dn", buff->total_size);

作为一个良好的实践,您可以将 freed指针设置为NULL

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

要使这种情况失效,通常在您free()分配给指针的内存后,您应该将其设置为NULL。取消引用NULL也是UB,但至少在调试时,您可以看到不应该使用指针,因为它没有指向有效的内存地址。

[注释太长]

允许你的"析构函数"设置传递给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);
  ...

相关内容

  • 没有找到相关文章

最新更新