Why does a switch break cause a segmentation fault
Boris Carvajal
boris2.9 at gmail.com
Tue Jul 23 15:28:37 UTC 2019
On Tuesday, 23 July 2019 at 08:04:07 UTC, adamgoldberg wrote:
> On Tuesday, 23 July 2019 at 00:01:09 UTC, Exil wrote:
>> On Monday, 22 July 2019 at 22:05:17 UTC, adamgoldberg wrote:
>>> Hey, I just happened to be writing a program in D an stumbled
>>> upon a bug, that causes it to terminate after receiving a
>>> SEGV signal, nothing wierd so far but it looks everything I
>>> tried shows it is the break statement inside of a switch.
>>> It seems to have a relatively random chance of occuring, and
>>> also somewhat dependant on the compiler, and build mode used.
>>> I'm short on time so instead of rewriting my SO post I will
>>> just link it.
>>>
>>> Here!
>>> https://stackoverflow.com/questions/57153617/random-segmentation-fault-in-d-lang-on-switch-break
>>>
>>> Hope someone can help!
>>
>> Could be the statement in the actual switch(), which is
>> accessing a pointer "codecpar".
>>
>> switch (stream.codecpar.codec_type)
>> ^^^^^
>>
>> This could be null and you aren't checking for it. I find that
>> D sometimes doesn't have the correct line numbers for debug
>> info, even when not doing an optimized build. So it could
>> really be anything in that function.
>>
>> The root cause could be a lot of things though, some bad
>> codegen or otherwise. Could add a check to make sure though.
>
> I ran the program after adding
>
> enforce (stream.codecpar != null);
>
> and nothing changed, and by nothing I mean that DMD in debug
> mode still doesnt crash but DMD in release does (like 70% of
> the time), I think its more important to address that issue
> because I can't seem to find any explenation of this behaviour,
> yet it occurs.
The struct AVStream is different on the D side (avformat.d) than
the original C header, at least on my PC using ffmpeg 4.1.4.
So instead of getting codecpar member we get some unrelated data
and dereferencing it can crash the program.
I tried using the DPP project, it errors out but the generated
file is almost there, just commenting 1 line and changing some
not found type pointer member to void pointer I got a working
example with your same code.
Here is the updated struct part, the program will run fine with
this layout.
struct AVStream
{
int index;
int id;
AVCodecContext* codec;
void* priv_data;
AVRational time_base;
c_long start_time;
c_long duration;
c_long nb_frames;
int disposition;
AVDiscard discard;
AVRational sample_aspect_ratio;
AVDictionary* metadata;
AVRational avg_frame_rate;
AVPacket attached_pic;
AVPacketSideData* side_data;
int nb_side_data;
int event_flags;
AVRational r_frame_rate;
char* recommended_encoder_configuration;
AVCodecParameters* codecpar;
static struct _Anonymous_9
{
c_long last_dts;
c_long duration_gcd;
int duration_count;
c_long rfps_duration_sum;
double[399]** duration_error;
c_long codec_info_duration;
c_long codec_info_duration_fields;
int frame_delay_evidence;
int found_decoder;
c_long last_duration;
c_long fps_first_dts;
int fps_first_dts_idx;
c_long fps_last_dts;
int fps_last_dts_idx;
}
_Anonymous_9 _anonymous_10;
auto last_dts() @property @nogc pure nothrow { return
_anonymous_10.last_dts; }
void last_dts(_T_)(auto ref _T_ val) @property @nogc pure
nothrow { _anonymous_10.last_dts = val; }
auto duration_gcd() @property @nogc pure nothrow { return
_anonymous_10.duration_gcd; }
void duration_gcd(_T_)(auto ref _T_ val) @property @nogc
pure nothrow { _anonymous_10.duration_gcd = val; }
auto duration_count() @property @nogc pure nothrow {
return _anonymous_10.duration_count; }
void duration_count(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.duration_count = val; }
auto rfps_duration_sum() @property @nogc pure nothrow {
return _anonymous_10.rfps_duration_sum; }
void rfps_duration_sum(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.rfps_duration_sum = val; }
auto duration_error() @property @nogc pure nothrow {
return _anonymous_10.duration_error; }
void duration_error(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.duration_error = val; }
auto codec_info_duration() @property @nogc pure nothrow {
return _anonymous_10.codec_info_duration; }
void codec_info_duration(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.codec_info_duration = val; }
auto codec_info_duration_fields() @property @nogc pure
nothrow { return _anonymous_10.codec_info_duration_fields; }
void codec_info_duration_fields(_T_)(auto ref _T_ val)
@property @nogc pure nothrow {
_anonymous_10.codec_info_duration_fields = val; }
auto frame_delay_evidence() @property @nogc pure nothrow
{ return _anonymous_10.frame_delay_evidence; }
void frame_delay_evidence(_T_)(auto ref _T_ val)
@property @nogc pure nothrow { _anonymous_10.frame_delay_evidence
= val; }
auto found_decoder() @property @nogc pure nothrow {
return _anonymous_10.found_decoder; }
void found_decoder(_T_)(auto ref _T_ val) @property @nogc
pure nothrow { _anonymous_10.found_decoder = val; }
auto last_duration() @property @nogc pure nothrow {
return _anonymous_10.last_duration; }
void last_duration(_T_)(auto ref _T_ val) @property @nogc
pure nothrow { _anonymous_10.last_duration = val; }
auto fps_first_dts() @property @nogc pure nothrow {
return _anonymous_10.fps_first_dts; }
void fps_first_dts(_T_)(auto ref _T_ val) @property @nogc
pure nothrow { _anonymous_10.fps_first_dts = val; }
auto fps_first_dts_idx() @property @nogc pure nothrow {
return _anonymous_10.fps_first_dts_idx; }
void fps_first_dts_idx(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.fps_first_dts_idx = val; }
auto fps_last_dts() @property @nogc pure nothrow { return
_anonymous_10.fps_last_dts; }
void fps_last_dts(_T_)(auto ref _T_ val) @property @nogc
pure nothrow { _anonymous_10.fps_last_dts = val; }
auto fps_last_dts_idx() @property @nogc pure nothrow {
return _anonymous_10.fps_last_dts_idx; }
void fps_last_dts_idx(_T_)(auto ref _T_ val) @property
@nogc pure nothrow { _anonymous_10.fps_last_dts_idx = val; }
_Anonymous_9* info;
int pts_wrap_bits;
c_long first_dts;
c_long cur_dts;
c_long last_IP_pts;
int last_IP_duration;
int probe_packets;
int codec_info_nb_frames;
AVStreamParseType need_parsing;
AVCodecParserContext* parser;
AVPacketList* last_in_packet_buffer;
AVProbeData probe_data;
c_long[17] pts_buffer;
AVIndexEntry* index_entries;
int nb_index_entries;
uint index_entries_allocated_size;
int stream_identifier;
int program_num;
int pmt_version;
int pmt_stream_idx;
c_long interleaver_chunk_size;
c_long interleaver_chunk_duration;
int request_probe;
int skip_to_keyframe;
int skip_samples;
c_long start_skip_samples;
c_long first_discard_sample;
c_long last_discard_sample;
int nb_decoded_frames;
c_long mux_ts_offset;
c_long pts_wrap_reference;
int pts_wrap_behavior;
int update_initial_durations_done;
c_long[17] pts_reorder_error;
ubyte[17] pts_reorder_error_count;
c_long last_dts_for_order_check;
ubyte dts_ordered;
ubyte dts_misordered;
int inject_global_side_data;
AVRational display_aspect_ratio;
AVStreamInternal* internal;
}
More information about the Digitalmars-d-learn
mailing list