【问题标题】:Assign null to the address of a pointer将 null 分配给指针的地址
【发布时间】:2016-12-15 09:48:55
【问题描述】:

如何在 free_x 函数中取消初始化 x?我必须这样做才能适应 API 方法。我可以很容易地通过将 null 分配给 x 来取消初始化它,但我必须在 free_x 函数中执行它。

typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

int main(void)
{
    void *x;

    alloc_x(&x);
    free_x(x); // x = NULL works but not allowed

    return 0;
}

void alloc_x(void **param)
{
    *param = (my_struct *)&var;
}

void free_x(void *param)
{
    // how can I free param here?
}

【问题讨论】:

  • *param = NULL;.......?;
  • *param = NULL 应该可以工作
  • 指针的地址?还是指针指向的地址?
  • OT:*param = (my_struct *)&var; 这里的演员阵容毫无用处。就做*param = &var;
  • @sanchop22 那你不能。如果你想改变“你传递给free_x的东西指向的东西”(即将它设置为NULL),那么你必须传递一个指向指针的指针,就像你对alloc_x所做的那样。

标签: c pointers struct free pointer-to-pointer


【解决方案1】:

简单的回答:您的代码已经完成,所以不要再做。

解释:你没有​​分配内存(在堆、栈或其他地方),所以没有什么可以释放的。您不拥有任何必须返回的资源、设置任何需要清除的标志或增加任何需要递减的信号量等。

您正在实现一个 API,但仅仅因为有一个函数原型并不意味着您的实现必须做任何事情,如果它不需要的话。只需更改注释以说明无事可做并将函数留空即可。

void alloc_x(void **param)
{
    *param = &var; // No need to cast here, just assign.
}

void free_x(void *param)
{
    // Nothing allocated, taken, incremented, etc. in alloc_x, so ...
    // nothing to free, release, decrement, etc. here in free_x.
}

使用 API 的代码预计 paramx 指针后面的内存在调用后已被释放,因此它不应该在之后对其变量做任何事情。如果他们这样做,这不是你的问题,但如果你对调用者的 x 变量胡作非为,那将是你的问题!

【讨论】:

  • 您正在回答一个不是被问到的问题。而且struct my_struct这个问题有一个内部指针,所以很容易猜到free_x函数中的其他mallocated内存一定是freed。
  • +1 击中目标。我同意,在这种情况下我们不需要做任何事情。如果调用者在 free_x(..) 之后使用 x 这不是你的问题
【解决方案2】:

*param = NULL;

malloc 返回 void * 并且 free 需要 void *,所以你的一些演员是 毫无意义,而且你总是在释放一个 void * 即使你是 从其他类型的指针开始。

【讨论】:

  • 当我写 *param = NULL 时,我收到 ''expression must be a modifiable lvalue" 错误!
【解决方案3】:

如果不更改 alloc_x 函数,我认为这是不可能的。下面给出了一种可能的实现:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

void alloc_x(void **param)
{
    *param = malloc(sizeof(my_struct *));
    memcpy(*param,(my_struct *)&var,sizeof(my_struct *));
}

void free_x(void *param)
{
    free(param);
    // how can I free param here?
}
int main(void)
{
    void *x;

    alloc_x(&x);
    free_x(x); // x = NULL works but not allowed

    return 0;
}

【讨论】:

  • 没错,但我不能使用 malloc 和 free,因为我们正在开发微控制器,即使可以使用动态内存分配也是不允许的。
  • 在这种情况下,我可以问你为什么需要 alloc_x 和 free_x 吗?为什么不使用 MACRO 而不是函数。比如#define free_x(param) param = NULL
  • 因为我必须实现 free_x 函数才能适应 API 函数。我必须有 free_x(void *param) 函数,它应该在函数内部取消初始化 x。
  • 我不认为你可以通过将 free_x 中的 x 传递为 * 来取消初始化,如果这是你唯一的要求,最好使用 MACRO
【解决方案4】:

有点棘手,但你可以做到

#include <stdio.h>
#include <string.h>

typedef struct
{
    int field1;
    void *field2;
}my_struct;

static my_struct var;

void alloc_x(void **param)
{
    *param = (my_struct *)&var;
}

void free_x(void *param)
{
    memset(param, 0x00, sizeof(void *));
}

int main(void)
{
    void *x;

    alloc_x(&x);
    printf("Before: x=%p\n", x);
    free_x(&x);
    printf("After: x=%p\n", x);

    return 0;
}

void free_x(void *param)
{
    my_struct **p = param;

    *p = NULL;
}

显然它仅在使用void * 中有效

【讨论】:

  • 这也会破坏 var 变量的内容。不确定这是不是有意的。
  • 这不好。试图更改另一段代码中的 private 值的代码要么是设计上的错误,要么是等待发生的错误。
  • @A.N 我没听懂你
  • @LPs 是的,当您传递一个指向指针的指针时,就像alloc_x 函数中的情况一样。仅将指针传递给free_x 函数的事实表明调用者的副本(即原始x 变量)不打算被修改。如果要修改x,它确实会作为指向指针的指针传递。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 2021-01-18
相关资源
最近更新 更多