【问题标题】:Playing around with calloc() and free() in C在 C 中使用 calloc() 和 free()
【发布时间】:2021-10-09 00:35:45
【问题描述】:

我在玩 malloccallocfree,我注意到编译器向我发送了 3 个警告:

  1. “警告 C6011 取消引用 NULL 指针 'ptr'。” 20号线
  2. “警告 C4022 'free':实际参数 1 的指针不匹配”第 20 行
  3. “警告 C4047 '=':'int' 与 'void pointer' 的间接级别不同”第 21 行

代码如下:

int main(int argc, char* argv[], char* envp[])
{
    int* ptr = NULL;
    int size_b = 30;
    int i = 0;

    ptr = (int*)calloc(size_b, sizeof(int));

    if (ptr)
    {
        printf("%d", ptr[0]);
    }

    for (i; i < size_b; ++i)
    {
        free(ptr[i]);    // Line 20
        ptr[i] = NULL;   // Line 21
    }

    return 0;
}

程序运行,但我想知道这些错误的来源,以及是否有清除它们的方法。

【问题讨论】:

  • free() 的参数必须是一个指针。 ptr[i]int,而不是指针。
  • 基本上,free() 的参数必须是以前由malloc()calloc()realloc() 返回的指针。 ptr 是唯一这样的指针,而不是 ptr[i]
  • 您希望它做什么?当你分配一块内存时,你只能释放整个东西,你不能释放它的单个元素。
  • “程序运行”是一种错觉。第 20 和 21 行是undefined behavior
  • 没有 cmets,我们无法判断您希望这些代码行做什么。所以很难解释他们有什么问题。

标签: arrays c dynamic-memory-allocation free calloc


【解决方案1】:

在此声明中

free(ptr[i]);

表达式ptr[i] 的类型为int,而int 类型的对象的值为0

所以编译器发出消息

“警告 C4022 'free': 实际参数 1 的指针不匹配”

因为它需要一个指针类型为void * 的对象,该对象指向先前分配的内存,而不是int 类型。

注意本声明中的内容

ptr = (int*)calloc(size_b, sizeof(int));

分配了一个单独的内存区(用于整数数组),其地址存储在指针ptr 中。因此,要释放分配的内存范围,您需要编写

free( ptr );

然后在下一行中,您尝试将 void * 类型的空指针常量 NULL 分配给 int 类型的对象。

ptr[i] = NULL;

所以编译器发出消息

“警告 C4047 '=': 'int' 的间接级别与 'void 指针'"

至于这条消息

“警告 C6011 取消引用 NULL 指针 'ptr'。”

那么看来是因为前面的if语句

if (ptr)
{
    printf("%d", ptr[0]);
}

编译器认为如果控制是在这个 if 语句之后传递的(好像有一个 else 语句),那么指针 ptr 等于 NULL

您的程序没有多大意义。尽管如此,为了使其正确,您可以通过以下方式进行更改

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
    size_t n = 30;
    
    int *ptr = calloc( n, sizeof( int ) );

    if ( ptr )
    {
        for ( size_t i = 0; i < n; i++ )
        {
            printf( "%d ", ptr[i] );
        }
        putchar( '\n' );
    }

    free( ptr );
}

【讨论】:

    【解决方案2】:

    您正在分配给您的内存块ptr 要释放该内存,只需执行free(ptr); 您不要逐字释放;整个块立即被分配/释放(除非您使用realloc 分段执行操作)。

    只需替换

        for (i; i < size_b; ++i)
        {
            free(ptr[i]);    // Line 20
            ptr[i] = NULL;   // Line 21
        }
    

    free(ptr);
    

    您也不再需要i。为了安全起见,我还会将 delocation 移到 if (ptr) 下方。

    【讨论】:

    • 我怀疑你可能最接近 OP 的误解:如果你分配一个“整数块”,那么你只需释放“块”。不是每个单独的 int。
    • 我的印象是每个元素都必须被释放,我不知道它会为你释放整个块。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-01
    • 2021-11-12
    • 2011-05-05
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    相关资源
    最近更新 更多