2

私はTagLibで遊んでいます(Windowsでは、MingWで構築されています)。MP3 ファイルに ID3v1 または ID3v2 情報がない場合、TagLib に認識させようとしています。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;なく実行されます。また、 Icout << 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));
}

が true の場合create、真新しい空のタグを作成し、(set()関数を使用して) ベクトルに配置します。

これは、ファイルにタグが含まれているかどうかに関係なく、ベクターに追加されることを意味します。これは文書化された動作ではありません。バグのように見えます。

なぜこの 2 行が必要なのかはわかりません。このファイルの履歴を見ると、なぜ追加されたのかがわかるかもしれませんが、私はそうしませんでした。

とにかく、私はこのコードを実際に実行したことがないことを強調したいと思います。これは、大規模な問題を認識せずに、非常に小さな部分のみを純粋に静的に読み取ることに基づいています。

バグレポートを開くことは問題ないと思います。

于 2010-12-10T07:20:17.147 に答える
1

null ポインターを使用しても、必ずしもエラーが発生するとは限りません。それは未定義の動作です。機能しているように見えるかもしれませんし、本当に奇妙なことをするかもしれません。

この場合、コンパイラはおそらくthisポインターを null に設定して TagLib::ID3v2::Tag::album への呼び出しを生成していますが、これも保証されていません。関数内で何が起こるかは誰にもわかりません。

関数が NULL を返す可能性がある場合は、明示的にそれをチェックして、別のことを行う必要があります。

于 2010-12-10T02:23:11.117 に答える
0

私は同様の問題を抱えており、うまくいけば、ID3v1/ID3v2のプレゼンスチェックの回避策を見つけました。

それは方法ですvirtual bool TagLib::Tag::isEmpty() const

于 2011-07-15T12:51:01.833 に答える
0

Taglib は、ファイルに ID3v2Tag と ID3v1Tag がない場合、オブジェクトに「空の」ID3v2Tag と ID3v1Tag を作成します。

于 2010-12-10T05:23:11.407 に答える