2

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

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

  • blank.mp3下载),根本没有 ID3v1 或 ID3v2 信息。我可以通过在文件二进制内容中对“TAG”和“ID3”进行纯文本搜索来确认这一点。
  • only_album_id3v2.mp3下载),有ID3v2信息(只设置专辑)
  • only_album_id3v1.mp3下载),有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;
}

由于 NULL 指针错误,运行这个程序应该会中断,cout << at->album() << endl;但它运行得很好。此外,当 I 时cout << ct << 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。
程序完成。

4

4 回答 4

5

我简要检查了 TagLib 的代码。

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

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

但是,在函数结束时,就在返回之前,我们有 -

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

现在,Id3v2Tag(create)使用 true 参数,实际调用return d->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()函数)。

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

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

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

我认为打开错误报告不会有什么坏处。

于 2010-12-10T07:20:17.147 回答
1

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

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

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

于 2010-12-10T02:23:11.117 回答
0

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

于 2010-12-10T05:23:11.407 回答
0

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

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

于 2011-07-15T12:51:01.833 回答