【问题标题】:Why we don't have to free the embedded pointer of a struct in C为什么我们不必在 C 中释放结构的嵌入指针
【发布时间】:2011-12-06 16:43:38
【问题描述】:

我看到了以下code,

/* stack.c */
typedef struct Stack *StackPtr;

struct Stack
{
    int *mStack;
    int mCurSize;
};

StackPtr StackCreate()
{
    return (StackPtr) calloc(sizeof(struct Stack), 1);
}

void StackDestroy(StackPtr stack)
{
    if (stack)
    {
        free(stack);
    }
}

void StackPush(StackPtr stack, int val)
{
    if (! stack)
        return;

    if (stack->mStack)
    {
        int newsize = stack->mCurSize + 1;
        int *newptr = realloc(stack->mStack, sizeof(struct Stack)*newsize);
        if (newptr)
        {
            stack->mStack = newptr;
            stack->mStack[newsize-1] = val;
            stack->mCurSize = newsize;
        }
    }
    else
    {
        stack->mStack = malloc(sizeof(struct Stack));
        if (stack->mStack)
        {
            stack->mStack[0] = val;
            stack->mCurSize = 1;
        }
    }
}

int StackPop(StackPtr stack)
{
    if (! StackIsEmpty(stack))
    {
        return stack->mStack[--stack->mCurSize];
    }
    return 0;
}


void StackDestroyMyWay(StackPtr stack) // This is my understanding
{
    if (stack)
    {
        if (stack->mStack)
            free(stack->mStack);
        free(stack);
    }
}

int StackIsEmpty(const StackPtr stack)
{
    return stack == NULL || stack->mCurSize == 0;
}

/* main.c */
int main(int argc, char *argv[])
{
    /* Create a new stack */
    StackPtr stack = StackCreate();
    int val;

    /* push and pop a value to the stack */
    printf( "Empty: %d\n", StackIsEmpty(stack));
    StackPush(stack, 10);
    printf("Empty: %d\n", StackIsEmpty(stack));
    val = StackPop(stack);
    printf("Popped off: %d\n", val);
    printf("Empty: %d\n", StackIsEmpty(stack));

    /* clean up the stack */
    StackDestroy(stack);
    return 0;
}

问题> 我假设原始 StackDestory 已正确实现,但我不明白为什么我们不必明确释放 stack->mStack。

【问题讨论】:

  • 我认为你的方法是正确的。鉴于您向我们展示的内容,除非明确释放,否则 mStack 将泄漏。
  • 我认为您必须这样做,并且原始实现存在内存泄漏。除非它在您未显示的代码中的某处被释放:)
  • 我认为StackDestroyMyWay() 也是正确的。但是请注意,you don't have to check for null before free()。所以你可以说,if (stack) { free(stack->mStack); free(stack);}。
  • 对于每个 malloc/realloc/calloc,您需要调用一次 free。这是1-1的对应关系。

标签: c


【解决方案1】:

实际上你确实必须释放mStack 某处,否则你会泄漏内存。如果StackDestroy 不为你做,你以后必须自己做。

在设计用于分配和释放内容的 API 时,请考虑以下几点:

  • 客户端是否分配了对象?也许他也应该释放它。有没有可能他传递了一个不是通过malloc 获得的对象?
  • 除了我们的对象消亡之外,客户还能用对象做有用的事情吗?

在您的情况下,客户端甚至不知道 mStack 的存在(从技术上讲,您可以使用不透明对象),因此,由于 您 分配了它,因此您也应该释放它。

【讨论】:

  • 那么你认为StackDestroyMyWay这个函数实现正确了吗?
  • @q0987:我想每个人都这样做,除非有一些你不知道的细节......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-27
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多