6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

enumとintが同じ型だと仮定しないようにしよう

Posted at

眠い中数時間デバッグさせられた怒りに任せて書いています。

起こったこと :
3DSの自作ソフトのソースコード中で、かの有名なFFmpegのlibavfilterを初めて使ったところフィルターグラフ構築した後のavfilter_graph_config()が失敗を返す。

調べたところFFmpegのデバッグログを見るといいとか書いてあったからログのコールバック関数設定してエラーを見たら"Duplicated sample format"とのこと。このエラーがGoogleで微塵も引っ掛からない。

仕方がないのでFFmpegの中に潜り込んでいろいろデバッグ表示させたら以下のようなコードが原因なことが判明 :
※以下のコードにある2つの関数は本来別々のファイルにあります。

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    <省略>
};
static int query_formats(<省略>)
{
    <省略>
    static const enum AVSampleFormat sample_fmts[] = {
        AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
        AV_SAMPLE_FMT_NONE
    };
    <省略>
    formats = ff_make_format_list(sample_fmts);
    <省略>
}
AVFilterFormats *ff_make_format_list(const int *fmts)
{
    <省略>
    int count = 0;
    if (fmts)
        for (count = 0; fmts[count] != -1; count++);
    <省略>
}

AV_SAMPLE_FMT_NONE が-1に等しいので番兵の役割をしています。
ところがデバッグ表示していると ff_make_format_list の方では count が620にもなっているではないですか。
嫌な予感がしながら sample_fmts の要素の型を enum AVSampleFormat から int に変えると直ってしまいました。
つまりenum AVSampleFormatが4バイトではなかったようです。
実際この環境で

enum X {
    ABC = -1,
    DEF,
    GHI,
    JKL
};

に対して sizeof (enum X) は1になりました。

普通の環境のGCCだとenumはデフォルトではintでコンパイル時に-fshort-enumsを付けると必要最小限のバイト数になるらしいですが今回-fshort-enumsは付けていないつもりです。

余裕があったら本家にちょっとissueっぽいの立てるかもしれないけどあっちがどこまで変な環境をサポートするつもりなのかは調べてから行かないとダメそうですね。

しかしライブラリの中いじることになったのは初めてだ

6
5
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?