函数内部没有 malloc,怎么办?

free of malloc inside the function, how to do that?

我在 str 函数中创建了 malloc,我想释放这个 malloc 变量

#include <stdio.h>

char *str(void)
{
    // create the malloc
    char *string = malloc(2); // how to free it
    *(string + 0) = 'J';
    *(string + 1) = 'O';
    // return the malloc
    return string;
}

int main(void)
{
    // print the function
    printf("%s, str());
    return 0;
}
free(string)

会释放它。但是要 print 它作为一个字符串,你必须在最后有 [=15=]

注意:如果您计划在函数调用结束时 return 它,则不应在函数内部释放它。因为这可能会导致未定义的行为。

正确的做事方式:

char *str(void)
{
    // create the malloc
    char *string = malloc(3); // how to free it
    if(string){
       *(string + 0) = 'J';
       *(string + 1) = 'O';
       *(string + 2) = '[=11=]';
    // return the malloc
    }
    return string;
}

int main(void)
{
    // print the function
    char *s = str();
    if(s)
       printf("%s", s);
    free(s);
    return 0;
}

不正确

如果你这样做,那将是内存泄漏:

int main(void)
{
    // print the function
    printf("%s", str());
    return 0;
}

如果您这样做,那么当您尝试将其打印出来时就会出现未定义的行为。

char *str(void)
{
    // create the malloc
    char *string = malloc(2); // how to free it
    *(string + 0) = 'J';
    *(string + 1) = 'O';
    // return the malloc
    free(string);
    return string;
}

int main(void)
{
    // print the function
    printf("%s", str()); // undefined behavior. A dragon might appear.
    return 0;
}

通常让调用者提供打印缓冲区是更好的选择;如果打印确实成功,可以通过 return 值提示;新的函数签名可能如下所示:

#include <stdbool.h>

bool str(size_t length, char buffer[length])
{
    if(length < 3)
    {
        // buffer is too short...
        return false;
    }

    buffer[0] = 'J';
    buffer[1] = 'O';
    buffer[2] = 0; // terminating null character, which you ommitted!
}

注意忽略数组参数中的长度说明符(函数参数仅),定义等同于char buffer[]char* buffer;仍然指定长度可以用来告诉用户实际需要什么样的参数(-> 自文档代码);还要注意,这仅适用于 outer-most 维度(在 char[12][10]12 被忽略但不是 10,参数类型是等同于 char(*)[10],它是一个指向长度为 10 的数组的指针。

然后用户可以在堆或堆栈上动态分配字符串的位置:

int main(void)
{
    char stack[3];
    if(str(sizeof(stack), stack))
    {
        printf("%s", stack);
    }

    size_t len = 3;
    char* heap = malloc(len);
    if(!heap) // should always be checked!
    {
        // allocation failed!
        return -1; 
    }
    if(str(len, heap))
    {
        printf("%s", heap);
    }

    free(heap);

    return 0;
}

如果您仍想保留原始签名,那么您需要 returned 字符串两次,一次打印它,一次释放它——也就是说,您需要将它存储在一个中间变量中以便能够这样做:

int main(void)
{
    char* s = str(); // store it in a variable!
    printf("%s", s); // still need to append the null terminator for!!!
    free(s); // now you can free it

    return 0;
}

如果您不附加空终止符,那么您需要明确限制要打印到控制台的字符数:

printf("%.2s", s);
//       ^^  (!)