Linux D lang on开关断路器中的随机分段故障

Linux D lang on开关断路器中的随机分段故障,linux,d,dmd,ldc,Linux,D,Dmd,Ldc,我正在调试一个用D编写的相当简单的程序,它似乎有随机机会接收SEGV信号。 进一步检查后,我发现使用不同的编译器和构建模式会产生不同的结果 我的测试结果: DMD Debug=99%的时间有效 DMD释放=50/50 LDC调试=50/50 LDC释放=50/50 因为来自默认编译器(DMD)的二进制文件只有一次崩溃,我无法真正调试它,而且由于缺少调试符号,发布模式也没有帮助。 在调试模式下使用LDC构建二进制文件,让我用gdb和valgrind对其进行测试,以总结我收集的内容 valgri

我正在调试一个用D编写的相当简单的程序,它似乎有随机机会接收SEGV信号。 进一步检查后,我发现使用不同的编译器和构建模式会产生不同的结果

我的测试结果:

  • DMD Debug=99%的时间有效
  • DMD释放=50/50
  • LDC调试=50/50
  • LDC释放=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语句,那么现在呢

这是产生seg故障的代码片段

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.

那么,有没有人知道是什么导致了这种行为,或者更确切地说,是如何着手解决它的呢?

试着检查有效性\u流\u音频

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

尝试检查有效性\u流\u音频

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
的方式是有风险的

您没有遵守
toStringz
文档中的警告:

重要提示:当将char*传递给C函数,并且C函数出于任何原因保留它时,请确保在D代码中保留对它的引用。否则,它可能在垃圾收集周期中无效,并在C代码尝试使用它时导致严重错误


这可能不是问题的原因,但您使用
toStringz
的方式是有风险的

您是否尝试添加一些writeln来查看它是否真的是那一行,而不是像之前的那一行?我要检查的两件事是,如果_stream_audio在那里不为null,或者如果
作用域(失败)
被调用,那么我的错误是stream.discard,我在开关if(stream!=null)之前添加了一个检查问题仍然存在,我认为你在LDC的调试信息中遇到了这个错误:你能检查一下这行上是否有nullptr deref:“switch(stream.codecpar.codec_type)”(codecpar==null?@johan有人已经在dlang论坛上发布了这个错误,在添加了一个检查之后没有任何变化,我认为更重要的是,调试中的DMD不会崩溃,但发布中的DMD有70%的时间崩溃。我使用ldc只是因为我无法从dmd debug获得任何信息,因为它没有崩溃。代码在发布时中断而在调试时中断是很常见的:例如,当代码调用UB时经常发生这种情况。我认为如果你能准确地知道错误发生在哪一行,这会有所帮助。你能把开关改写成几个if-then-else吗?(debug lineinfo应该适合)编辑:或者将开关条件读入一个伪变量,然后打开它?那么我认为你也应该在读取时获得正确的调试行信息。你是否尝试添加一些writeln来查看它是否真的是那一行,而不是之前的那一行?我要检查的两件事是,如果_stream_audio在那里不为null,或者如果
作用域(失败)
被调用,那么我的错误是stream.discard,我在开关if(stream!=null)之前添加了一个检查问题仍然存在,我认为你在LDC的调试信息中遇到了这个错误:你能检查一下这行上是否有nullptr deref:“switch(stream.codecpar.codec_type)”(codecpar==null?@johan有人已经在dlang论坛上发布了这个错误,在添加了一个检查之后没有任何变化,我认为更重要的是,调试中的DMD不会崩溃,但发布中的DMD有70%的时间崩溃。我使用ldc只是因为我无法从dmd debug获得任何信息,因为它没有崩溃。代码在发布时中断而在调试时中断是很常见的:例如,当代码调用UB时经常发生这种情况。我认为如果你能准确地知道错误发生在哪一行,这会有所帮助。你能把开关改写成几个if-then-else吗?(debug lineinfo应该适合)编辑:或者将开关条件读入一个伪变量,然后打开它?然后我认为你也应该在读取时获得正确的调试行信息。这是重写中的一个错误,现在已修复,还请查看@comments解释为什么这将解决问题,并为用户提供最低限度的工作解决方案。这是重写中的一个错误,现在已修复,另请查看@comments,解释为什么这将解决问题,并为用户提供最低限度的工作解决方案