【问题标题】:How to check if a pointer has been freed如何检查指针是否已被释放
【发布时间】:2023-03-11 13:34:01
【问题描述】:

我是 C 的初学者。下面是我的场景 - 我在 main 函数中创建了一个指针变量,它已被传递给多个函数(在此示例中为 2 个级别)。其中一项功能可以释放它。现在我需要检查 Main 以查看指针是否被释放,这意味着我需要将 main() 中的 &str 的值设置为指向 NULL。不确定我的方法是否正确。任何帮助将不胜感激

void func2(char *str)   
{
    free(str); 
}

void func1(char *str)
{
   func2(str); 
}

int main()
{ 
   char *str;
   str=(char *) malloc(10);
   func1(str);
   if(str){ do something; }  // if condition to check whether str is freed 
}

【问题讨论】:

  • 您无法进行检查。这就是使手动内存管理变得困难的原因。
  • 当然有……而且一旦你了解了如何使用指针,就很简单了。
  • 您可以通过一些更改来做到这一点(不知道为什么@milleniumbug 另有说明),但您真的想要吗?总的来说,这是一个糟糕的设计。 C 中的内存管理主要围绕所有权展开。尽量清楚谁拥有什么内存,这样你遇到的问题就会少得多。
  • 顺便说一句,Don't cast malloc
  • @EdS。好的,显然我还没有阅读上下文 - 问题标题询问“如何检查指针是否已被释放?”我的评论在这里是准确的(好吧,你不能那样做),剩下的问题(没有代码)提出了一个不同的问题“如何在函数之外将指针标记为 NULL?”

标签: c pointers malloc free


【解决方案1】:
#include <stdio.h>
#include <stdlib.h>

func2(char **str)
{
        free(*str);                //free
        *str = NULL;               //Set to NULL
}

func1(char **str)                   //func1 receives as **
{
        func2(str);                //Pass pointer to func2()
}

int main()
{
        char *str = NULL;
        str=(char *) malloc(10);
        func1(&str);                //Pass Address of pointer to func1()

        if(str)                     //Check for NULL
        {
                printf("\n Not - Freed...\n");
        }
        else
        {
                printf("\n Freed...\n");
        }                                             
        return 0;
}

在 C 中,所有内容都是按值传递的。我建议研究http://www.cs.fsu.edu/~myers/cgs4406/notes/pointers.html以了解这一点。

【讨论】:

  • 你不需要创建指向指针的指针...指向指针...一旦你在 func1 中发送了 str 的地址,你已经有了它的地址,如果你传递一个也没关系将其复制到下一个 500 个函数调用,地址是相同的,您将通过使用单个 * 取消引用来更改 str
  • @nightshade 对。已更新。
【解决方案2】:

你可以尝试这样的事情——首先重新定义 malloc 和 free (track.h)

#ifndef track_h
#define track_h
extern void* trackmalloc(size_t size);
extern void trackfree(void* array);
extern void trackismalloc(void* array);
#define malloc trackmalloc
#define free trackfree

#endif

然后对于每段使用 malloc 和 free 的代码,将 #include 替换为 #include "track.h"

#include <stdlib.h>
#include <stdio.h>
#include "track.h" /* was <malloc.h> */

// A function which has a 20% chance of freeing the pointer
void twentypercent(char* array)
{
    if (rand() < (RAND_MAX / 5))
        free(array);
}


int main(int argc, char* argv[])
{
    char* list = malloc(256);
    int ii;

    for (ii = 0; ii < 10; ++ii)
        twentypercent(list);

    if (trackismalloc(list)
        printf("Not freed yet");

    return 0;
}

现在定义 track.c。这只会释放由 trackmalloc 分配的内存。如果不是trackmalloc分配的,就会报内存已经被释放了。

#include <stdio.h>
#include <malloc.h>
#define TRACKER_MAX 2048
static void* tracker[TRACKER_MAX] = { 0 };
static int track_last = -1;
void* trackmalloc(size_t size)
{
    // For simplicity, tracker will not be reused
    tracker[++track_last] = malloc(size);
    return tracker[track_last];
}

void trackfree(void* array)
{
    // This will slow down as the list gets filled up.
    // You will need a more efficient way of searching lists (possibly bsearch)
    int tt;
    for (tt = 0; tt < track_last; ++tt)
    {
        if (array == tracker[tt])
        {
            free(tracker[tt]);
            tracker[tt] = 0;
            break;
        }
    }

    if (tt == track_last)
        printf("%p already freed\n", array);
}

int trackismalloc(void* array)
{
    // This will slow down as the list gets filled up.
    // You will need a more efficient way of searching lists (possibly bsearch)
    int tt, result = 0;
    for (tt = 0; tt < track_last; ++tt)
    {
        if (array == tracker[tt])
        {
            result = 1;
            break;
        }
    }
    return result;
}

【讨论】:

    【解决方案3】:
    void func1(char** str) {
        free(*str);
        *str = NULL;
    }
    
    void func2(char** str) {
        free(*str);
        *str = NULL;
    }
    
    int main() {
        char *str;
    
        str = (char*) malloc(10);
        func1(&str);
        if (str) {
            do something;
        }
    }
    

    【讨论】:

    • func1() 应该调用func2(),而不是free()
    • 是的,这是避免编写冗余代码的一个好点,但我只是假设在 func1() 和 func2() 中可能会做其他事情;它们完全用于不同的功能。
    • 如果 free 没有被调用,这个值会留在内存中;所以 freedelloc 必须按照 C 标准惯例调用。
    • 只有代码的答案,特别是没有任何 cmets 可言,是不好的形式。
    • 谢谢你的cmets,伙计。
    【解决方案4】:
    void func2(char **str)   
    {
        free(*str); 
        *str = 0;
    }
    
    void func1(char **str)
    {
       func2(str); 
    }
    
    int main()
    { 
       char *str;
       // I'd recommend using sizeof(type_you_want) * amount_of_elements instead of
       // a constant number: ->  malloc(sizeof(char) * 10);
    
       str=(char *) malloc(10);
    
       func1(&str); // You must pass the address of the pointer, because you want
                   // to change "WHAT IT POINTS TO", not "WHAT IS POINTED BY IT"
    
       if(str){ do something; }  // if condition to check whether str is freed 
    }
    

    当您在 C 中调用函数时,您传递了这些参数的副本,因此您传递了该指针的副本(该副本仍然指向同一个位置,因此您可以更改它指向的那个位置)但是你想改变指针值,所以你需要传递它的地址。

    我已经解释了一点如何在here中使用函数内部的指针

    【讨论】:

      【解决方案5】:
      #include <stdio.h>
      #include <stdlib.h>
      
      void func2(char **str)
      {
          printf("%d %s\n",__LINE__,__func__);
          free(*str);
          *str = NULL;
      }
      
      void func1(char **str)
      {
          printf("%d %s\n",__LINE__,__func__);
          func2(str);
      }
      
      char * allocaMem(char **ptr)
      {
          *ptr=(char *) malloc(sizeof(char)* 10);
          if(!*ptr)
          {
              perror("");
          }
          else
          {
              return *ptr;
          }
      }
      
      int main()
      {
          char *str = allocaMem(&str);
          if (!str) {
              printf("Error in malloc()\n");
              return -1;
          }
      
          func1(&str);
      
          if (str) {
              printf("Memory Not freed\n");
          } else {
              printf("Memory freed\n");
          }
      }
      

      【讨论】:

      • 只有代码的答案,特别是没有任何 cmets 可言,是不好的形式。
      猜你喜欢
      • 2012-01-08
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      相关资源
      最近更新 更多