问题C中的自由函数的指针

时间:2019-01-21 13:39:53

标签: c visual-studio-2017 free dynamic-memory-allocation realloc

我有两个指针,我想用指针somme中包含的值填充指针v

这是方法:

somme[0]=v[0] + v[1];
somme[1]=v[2] + v[3];
somme[2]=v[4] + v[5];

...

执行distruggi_vec(somme);功能而不执行distruggi_vec(v);时发生错误。

你有什么想法吗?谢谢您的宝贵时间。

这是我的c代码:

#include <stdlib.h>
#include <stdint.h>

extern uint32_t *crea_vec(size_t  n)
{
    uint32_t *p;
    p = malloc(n * sizeof(uint32_t));
    for (size_t i = 0; i < n; ++i)
    {
        p[i] = i;
    }

    return p;
}

uint32_t *somme_2a2(uint32_t *vett, size_t size) 
{
    if (size % 2 != 0) 
    {
        size = size - 1;
    }

    size_t j = 0;
    for (size_t i = 0; i < size; ++i) 
    {
        if (i >= 10) { goto a; }
        j = i * 2;
        vett[i] = vett[j] + vett[j + 1];
    }
    a:
    size = size / 2;
    vett = realloc(vett, size * sizeof(uint32_t));

    return vett;
}

extern void distruggi_vec(uint32_t *p)
{
    free(p);
}

int main(void) 
{
    size_t n = 20;
    uint32_t *v = crea_vec(n);
    uint32_t *somme = somme_2a2(v, n);
    distruggi_vec(v);
    distruggi_vec(somme);

    return 0;
}

当我调试代码时,它给了我这个问题:

3 个答案:

答案 0 :(得分:3)

首先,不要像这样写代码

 vett = realloc(vett, size * sizeof(uint32_t));

如果realloc()失败,您也将丢失原始指针。

C11的第7.22.3.5章起

  

如果不能为新对象存储   分配后,旧对象不会被释放,其值保持不变。

  

realloc函数返回一个指向新对象的指针(该对象可能具有相同的指针   值作为指向旧对象的指针),如果新对象不能为null,则返回null指针   已分配。

始终在临时指针中捕获realloc()的返回值,并与NULL进行比较,如果有效,则可以(可选)将其分配回原始指针。类似于(伪代码)

pointer temp = NULL;
temp = realloc (oldPOinter, size);
if (!temp) 
{
    printf ("Some error message");
    return SOME_ERROR_CODE;
}
oldPOinter = temp;

也就是说,这里的问题是,在realloc()成功的情况下,将不再使用原始指针。 v作为参数传递给somme_2a2(),根据C,它按值传递。因此,对vett所做的任何更改都不会反映回v中的呼叫者。

但是,由于realloc()通过vett将存储器指针的有效性更改为somme_2a2(),因此在从main()调用成功返回之后,在v中,{{1 }}不再有效,您无需将其传递给free()

引用C11,第7.22.3.5章

  

realloc函数释放由ptr指向的旧对象,并返回一个   指向具有size指定大小的新对象的指针。 [...]

vett传递给free()会引起不确定的行为,因为您最终将尝试free() -d的指针[{ free()]。

引用第7.22.3.3节

  

[...]如果   该参数与内存管理器先前返回的指针不匹配   函数,或者如果通过调用realloc()free释放了空间,则   行为是不确定的。

答案 1 :(得分:1)

您对realloc的调用次数无关紧要,您仍然只有一个指针:{{1 }},malloccalloc

在调用realloc之后,原始指针将变为无效,您只能使用它返回的指针。

这意味着当您使用无效的指针realloc调用distruggi_vec时,您将拥有undefined behavior

答案 2 :(得分:1)

谢谢您的时间,这是我的问题的最终解决方案,没有错误:

代码:

`

#include <stdlib.h>
#include <stdint.h>

extern uint32_t *crea_vec(size_t  n)
{
    uint32_t *p;
    p = malloc(n * sizeof(uint32_t));
    for (size_t i = 0; i < n; ++i)
    {
        p[i] = i;
    }

    return p;
}

uint32_t *somme_2a2(uint32_t *vett, size_t size) 
{
    uint32_t *vett2 = calloc(size/2, sizeof(uint32_t));
    if (size % 2 != 0) 
    {
        size = size - 1;
    }

    size_t j = 0;
    for (size_t i = 0; i < size; ++i) 
    {
        if (i >= 10) { break; }
        j = i * 2;
        vett[i] = vett[j] + vett[j + 1];
        vett2[i] = vett[i];
    }

    return vett2;
}

extern void distruggi_vec(uint32_t *p)
{
    free(p);
}

int main(void) 
{
    size_t n = 20;
    uint32_t *v = crea_vec(n);
    uint32_t *somme = somme_2a2(v, n);
    distruggi_vec(v);
    distruggi_vec(somme);

    return 0;
}

`