Случайная ошибка сегментации в D lang при разрыве переключателя

Я отлаживал довольно простую программу, написанную на D, которая, кажется, имеет случайный шанс получить сигнал SEGV. При дальнейшем осмотре я заметил, что использование разных компиляторов и режимов сборки дало разные результаты.

Результаты моих тестов:

  • Отладка DMD = работает 99% времени
  • DMD Release = 50/50
  • LDC Debug = 50/50
  • LDC Release = 50/50

Поскольку двоичный файл из компилятора по умолчанию (DMD) зависал только один раз, я не смог его отладить, и режим выпуска тоже не помог из-за отсутствия символов отладки. Сборка двоичного файла с LDC в режиме отладки позвольте мне протестировать его с помощью gdb и valgrind, чтобы подвести итог тому, что я собрал.

Соответствующая информация от Valgrind,

Invalid read of size 4 @ ctor in file video.d line 46

Access not within mapped region at address 0x0 @ ctor in file video.d line 

Gdb не дает мне больше понимания, 3 стековых фрейма, из которых интересен только 0-й, обратная трассировка фрейма 0 показывает файл video.d строка 46, которая является оператором break, и что теперь?

Это фрагмент кода, вызывающий ошибку сегмента

module video;

import ffmpeg.libavformat.avformat;
import ffmpeg.libavcodec.avcodec; 
import ffmpeg.libavutil.avutil;

class Foo
{
    private
    {
        AVFormatContext* _format_ctx;
        AVStream* _stream_video;
        AVStream* _stream_audio;
    }

    ...

    public this(const(string) path)
    {
        import std.string : toStringz;

        _format_ctx = null;
        enforce(avformat_open_input(&_format_ctx, path.toStringz, null, null) == 0);
        scope (failure) avformat_close_input(&_format_ctx);

        enforce(avformat_find_stream_info(_format_ctx, null) == 0);
        debug av_dump_format(_format_ctx, 0, path.toStringz, 0);

        foreach (i; 0 .. _format_ctx.nb_streams)
        {
            AVStream* stream = _format_ctx.streams[i];

            if (stream == null)
                continue;

            enforce (stream.codecpar != null);

            switch (stream.codecpar.codec_type)
            {
                case AVMediaType.AVMEDIA_TYPE_VIDEO:
                    _stream_video = stream;
                    break;
                case AVMediaType.AVMEDIA_TYPE_AUDIO:
                    _stream_audio = stream;
                    break;
                default:
                    stream.discard = AVDiscard.AVDISCARD_ALL;
                    break; // Magic line 46
            }
        }
    }
}

// Might contain spelling errors, had to write it by hand.

Так у кого-нибудь есть идея, что вызывает такое поведение, или, точнее, как его исправить?

2 ответа

Попробуйте проверить достоверность _stream_audio

default:
    enforce( _stream_audio, new Exception( "_stream_audio is null" ))
        .discard = AVDiscard.AVDISCARD_ALL;
    break; // Magic line 46

Вы не соблюдаете предупреждение в toStringz документация:

"Важное примечание: при передаче char* в функцию C, и функция C сохраняет его по любой причине, убедитесь, что вы сохранили ссылку на него в своем D-коде. В противном случае он может стать недействительным во время цикла сборки мусора и вызвать неприятную ошибку, когда код C пытается его использовать ".

Это может быть не причиной вашей проблемы, а тем, как вы используете toStringz рискованно

Другие вопросы по тегам