意外的非NULL返回

Joe*_*gen 2 c++ windows taglib

我正在使用TagLib(在Windows上,使用MingW构建).我想让TagLib识别MP3文件中没有ID3v1或ID3v2信息.根据TagLib文档,当文件中没有ID3v2信息时,MPEG File对象中的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;
}
Run Code Online (Sandbox Code Playgroud)

由于NULL指针错误cout << at->album() << endl;,运行此程序应该会中断,但运行正常.此外,当我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;
}
Run Code Online (Sandbox Code Playgroud)

这是输出.

测试.
at不是NULL.
bt不是NULL.
ct不是NULL.
该计划已经完成.

Hex*_*gon 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);
Run Code Online (Sandbox Code Playgroud)

现在,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));
}
Run Code Online (Sandbox Code Playgroud)

所以,create当真实时,我们正在创建一个全新的空标记并将其放在向量中(使用该set()函数).

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

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

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

我认为打开错误报告不会有害.