从函数返回struct会导致内存损坏

时间:2015-01-07 16:35:44

标签: c ffmpeg

我试图将FFmpeg AVDictionary结构从一个函数返回到另一个函数。我写了以下两个函数:

int get_p_metadata(State **ps, AVDictionary *metadata) {
    printf("get_p_metadata\n");

    State *state = *ps;

    if (!state || !state->pFormatCtx) {
        return FAILURE;
    }

    metadata = NULL;
    av_dict_copy(&metadata, state->pFormatCtx->metadata, 0);

    printf("count in get_p_metadata %d\n", metadata->count);

    return SUCCESS;
}

int get_metadata(State **ps) {
    printf("get_metadata\n");

    AVDictionary m;
    get_p_metadata(ps, &m);
    printf("count in get_metadata %d\n", (&m)->count);

    return SUCCESS;
}

代码编译并运行但是当我调用get_metadata函数时,生成的输出是:

count in get_p_metadata 12
count in get_metadata 2073109240

有人可以解释为什么每次运行此代码时count的值会从12变为随机值吗?一旦get_p_metadata函数返回,为什么不保留12的值?我该如何解决这个问题?

更新

此解决方案有效(感谢Cornstalks实际阅读FFmpeg文档和 链接答案):

int get_p_metadata (State **ps, AVDictionary **metadata) {
    printf("get_p_metadata\n");

    State *state = *ps;

    if (!state || !state->pFormatCtx) {
        return FAILURE;
    }

    av_dict_copy(metadata, state->pFormatCtx->metadata, 0);

    return SUCCESS;
}

int get_metadata(State **ps, AVDictionary *metadata) {
    printf("get_metadata\n");

    AVDictionary *m = NULL;
    get_p_metadata (ps, &m);
    printf("count in get_metadata %d\n", m->count);

    return SUCCESS;
}

6 个答案:

答案 0 :(得分:3)

实际上,在您的get_p_metadata()中,您有一个参数AVDictionary *metadata

您可以将其视为get_p_metadata()中的局部变量。 因此,&metadata将引用局部变量,而不是m中的get_metadata()变量。

get_p_metadata()开始时,metadata设置为m的地址,然后将其重置为NULL。

您应该尝试以下方法:

int get_metadata (State **ps)
{
    AVDictionary *m = NULL;
    get_p_metadata (ps, &m);
    av_dict_free (&m);
    return SUCCESS;
}

int get_p_metadata (State **ps, AVDictionary **metadata)
{
    /* ... */

    av_dict_copy (metadata, state->pFormatCtx->metadata, 0);

    /* ... */
}

这样,如果av_dict_copy()AVDictionary*metadata将为NULL分配内存,这是现在的初始值。

最后av_dict_free()将释放字典中使用的内存。

答案 1 :(得分:2)

您从两个语句中得到不同的答案,因为它们是打印不同对象的字段。虽然get_metadata()&m传递给get_p_metadata(),但该函数完全忽略了传递的值,并将参数值重新分配给NULL。坦率地说,我很惊讶你没有得到段错误。

我认为设置metadata = NULL的目的是创建一个新的元数据对象,但是接收指向该新元数据对象的指针的局部变量与传递给该函数的参数之间没有任何联系。

也许你想要

int get_p_metadata(State **ps, AVDictionary **metadata) {
    ...
}

int get_metadata(State **ps) {
    printf("get_metadata\n");

    AVDictionary *m;
    get_p_metadata(ps, &m);
    printf("count in get_metadata %d\n", m->count);

    // NOTE: *m was dynamically allocated and needs to be cleaned up or returned

    return SUCCESS;
}

答案 2 :(得分:1)

根据av_dict_copy的声明:第一个参数“dst”是指向AVDictionary结构的指针。如果* dst为NULL,则此函数将为您分配一个结构并将其放入* dst

对于你的代码,你不应该将“元数据”分配给NULL,因为它已经指向AVDictionary结构,那么它应该没问题。

如果metedata为NULL,则表示av_dict_copy创建一个新的AVDictionary结构并更改其中的值,而get_metadata(State ** ps)中定义的结构保持不变,因此您可以获得任意的vaules。

答案 3 :(得分:-1)

这些陈述中有什么意义?!

metadata = NULL;
av_dict_copy(&metadata, state->pFormatCtx->metadata, 0);

如果将指针传递给对象m作为第二个函数的参数

AVDictionary m;
get_p_metadata(ps, &m);

然后你似乎要使用它的值或对象本身。否则传递指针是没有意义的。

答案 4 :(得分:-1)

此代码deosnt有意义

  metadata = NULL;
    av_dict_copy(&metadata, state->pFormatCtx->metadata, 0);

你传入了一个我想要更新的元数据对象的指针。现在将该指针设置为null,调用一个更新该指针的函数。由于我们无法看到你的其他功能很难知道你的意图所以我不能建议修复

答案 5 :(得分:-1)

在调用metadata之前,您将av_dict_copy设置为空指针。我想知道为什么它甚至可以工作,并假设av_dict_copy做了一些不同于你预期的事情(即设置一个值为AVDictionary *,其地址作为第一个参数传递)。无论哪种方式,您都失去了与本地AVDictionary m的连接,而2073109240只是内存中的一些随机值。