【问题标题】:Unexpected Non-NULL return意外的非 NULL 返回
【发布时间】:2010-12-10 00:59:54
【问题描述】:

我正在使用 TagLib(在 Windows 上,使用 MingW 构建)。我试图让 TagLib 识别 MP3 文件中何时没有 ID3v1 或 ID3v2 信息。根据TagLib documentation,当文件中没有 ID3v2 信息时,MPEG 文件对象中的 ID3v2Tag() 函数应该返回一个 NULL 指针。

很遗憾,这并没有发生。我有一些我在我的代码中使用的测试 MP3 文件(我已经使这些文件可用):

  • blank.mp3 (download),根本没有 ID3v1 或 ID3v2 信息。我可以通过在文件二进制内容中对“TAG”和“ID3”进行纯文本搜索来确认这一点。
  • only_album_id3v2.mp3 (download),有ID3v2信息(只设置了专辑)
  • only_album_id3v1.mp3 (download),有ID3v1信息(只设置了专辑)

这是我的代码。

#include <iostream>

#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>

using namespace std;

int main()
{
    cout << "Test." << endl;

    TagLib::MPEG::File a("tests/other/blank.mp3");
    TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
    TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");


    TagLib::ID3v2::Tag * at = a.ID3v2Tag();
    TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
    TagLib::ID3v2::Tag * ct = c.ID3v2Tag();

    cout << at->album() << endl;
    cout << bt->album() << endl;
    cout << ct->album() << endl;

    cout << "The program is done.";

    return 0;
}

由于cout &lt;&lt; at-&gt;album() &lt;&lt; endl; 上的空指针错误,运行该程序应该会中断,但它运行得很好。另外,当我cout &lt;&lt; ct &lt;&lt; endl;时,它返回一个内存地址。

这是输出:

测试。

测试专辑id3v2

程序完成。

编辑: 这是一个新的测试。

#include <iostream>

#include <mpeg/mpegfile.h>
#include <mpeg/id3v2/id3v2tag.h>

using namespace std;

int main()
{
    cout << "Test." << endl;

    TagLib::MPEG::File a("tests/other/blank.mp3");
    TagLib::MPEG::File b("tests/id3v2/only_album_id3v2.mp3");
    TagLib::MPEG::File c("tests/id3v1/only_album_id3v1.mp3");


    TagLib::ID3v2::Tag * at = a.ID3v2Tag();
    TagLib::ID3v2::Tag * bt = b.ID3v2Tag();
    TagLib::ID3v2::Tag * ct = c.ID3v2Tag();

    if(at == NULL)
    {
        cout << "at is NULL.";
    }
    else
    {
        cout << "at is not NULL.";
    }
    cout << endl;

    if(bt == NULL)
    {
        cout << "bt is NULL.";
    }
    else
    {
        cout << "bt is not NULL.";
    }
    cout << endl;

    if(ct == NULL)
    {
        cout << "ct is NULL.";
    }
    else
    {
        cout << "ct is not NULL.";
    }
    cout << endl;

    cout << "The program is done.";

    return 0;
}

这是输出。

测试。
at 不为 NULL。
bt 不为 NULL。
ct 不为 NULL。
程序完成。

【问题讨论】:

  • 你期待什么?例外?如果我没看错的话,您将 NULL 值传递给一个流,该流不会在控制台中输出。这不是预期的吗?
  • The program is done. 真的输出了吗?因为我在你的源代码中没有看到。
  • @Kissaki,如果 ct 为 NULL,cout &lt;&lt; ct &lt;&lt; endl; 不应该向流输出 0 吗?此外,我修复了代码示例以匹配输出。之前,我更新了输出,但没有更新代码。现在他们匹配了
  • 我不确定。不过,就我个人而言,为 NULL 不打印任何内容对我来说会更直观。不知道规格或任何内容怎么说。 /e:哦,那个输出现在很有趣。 :)

标签: c++ windows taglib


【解决方案1】:

我简要检查了 TagLib 的代码。

我对此一无所知,也从未使用过它,但代码对我来说看起来有问题。这就是为什么-

在 MPEG::File::read() 中,我们正在寻找一个标签 - d-&gt;ID3v2Location = findID3v2();。如果它不存在,则不会添加到标签向量中。这是支票 - if(d-&gt;ID3v2Location &gt;= 0)

然而,在函数的最后,就在返回之前,我们有 -

// Make sure that we have our default tag types available.
ID3v2Tag(true);
ID3v1Tag(true);

现在,Id3v2Tag(create) 带有一个 true 参数,实际上调用了 return d-&gt;tag.access(ID3v2Index, create);。 access() 函数是 -

template <class T> T *access(int index, bool create)
{
  if(!create || tag(index))
    return static_cast<T *>(tag(index));

  set(index, new T);
  return static_cast<T *>(tag(index));
}

所以当create 为真时,我们将创建一个全新的空标签并将其放置在向量中(使用set() 函数)。

这意味着无论文件是否包含标签,它们都会被添加到向量中。这不是记录在案的行为。看起来像一个错误。

我不知道为什么需要这两行 - 查看此文件的历史可能会暗示为什么要添加它们,但我没有这样做。

无论如何,我想强调的是,我从未真正执行过这段代码。这是基于仅静态读取非常小的部分,而没有意识到大规模问题。

我认为打开错误报告并没有什么坏处。

【讨论】:

  • 为了避免可能的错误,我没有对这两个调用进行注释,而是添加了三个返回私有布尔值的附加函数(hasID3v2、hasID3v1、hasAPE)。感谢您指出这一点!
  • 我查看了文件历史记录,结果发现这些行是由5 years ago 引入的。无论如何,我想知道如何检查 id3 标签是否可用,所以我在保存时不会伤害错误的文件(例如 m4a)?
  • 我已经提交了a bug report以防万一。
【解决方案2】:

使用空指针不一定会导致您看到的任何错误;这是未定义的行为。它可能看起来有效,或者它可能会做一些非常非常奇怪的事情。

在这种情况下,编译器可能会在 this 指针设置为 null 的情况下生成对 TagLib::ID3v2::Tag::album 的调用,但即使这样也不能保证。函数内部发生的事情是任何人的猜测。

如果函数可以返回 NULL,你应该明确地检查它并做一些不同的事情。

【讨论】:

  • 我想我明白你在说什么,我更新了我的问题以适应你的建议。问题依然存在。
【解决方案3】:

如果文件没有,Taglib 在对象中创建一个“空”ID3v2Tag 和 ID3v1Tag。

【讨论】:

  • 据我了解,只有将 TRUE 传递给 MPEG 文件对象的 ID3v2Tag() 函数。
  • 可以,但是在类TagLib::MPEG::File的构造函数中调用ID3v2Tag和ID3v1Tag,参数为TRUE。
【解决方案4】:

我遇到了类似的问题,希望我找到了 ID3v1/ID3v2 存在检查的解决方法。

方法virtual bool TagLib::Tag::isEmpty() const

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-26
    • 2014-07-26
    • 1970-01-01
    • 2013-11-25
    相关资源
    最近更新 更多