我正在使用TagLib(在Windows上,使用MingW构建)。我想让TagLib识别MP3文件中没有ID3v1或ID3v2信息。根据{{3}},当文件中没有ID3v2信息时,MPEG File对象中的ID3v2Tag()函数应返回NULL指针。
不幸的是,这种情况并未发生。我有一些我在我的代码中使用的测试MP3文件(我已经提供了文件):
这是我的代码。
#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 << at->album() << endl;
上的NULL指针错误,运行此程序应该会中断,但运行正常。此外,当我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 该计划已经完成。
答案 0 :(得分: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()
函数)。
这意味着无论文件是否包含标签,都会将它们添加到矢量中。这不是记录在案的行为。看起来像个bug。
我不知道为什么需要这两行 - 看看这个文件的历史可能会暗示它们为什么被添加,但我没有这样做。
无论如何,我想强调我从未真正执行过这段代码。这是基于纯粹静态读取非常小的部分,而不是意识到大规模的问题。
我认为打开错误报告不会有害。
答案 1 :(得分:1)
使用空指针不一定会导致您看到任何错误;这是未定义的行为。它似乎可行,或者它可能会做一些非常奇怪的事情。
在这种情况下,编译器可能会生成对TagLib :: ID3v2 :: Tag :: album的调用,并将 this 指针设置为null,但即使这样也无法保证。函数内部发生的是任何人的猜测。
如果函数可以返回NULL,那么你应该明确地检查它并做一些不同的事情。
答案 2 :(得分:0)
如果文件没有,Taglib会在对象中创建一个“空”ID3v2Tag和ID3v1Tag。
答案 3 :(得分:0)
我遇到了类似问题,希望我找到了ID3v1 / ID3v2状态检查的解决方法。