English 中文(简体)
我如何在一项C方案中确定分离错误? [复制]
原标题:How can I fix a segmentation fault in a C program? [duplicate]
This question already has answers here:
Closed 11 years ago.

Possible Duplicate:
Segmentation fault

Currently I am upgrading an open source program used for HTTP streaming. It needs to support the latest FFmpeg. The code compiles fine without any warnings, although I am getting a segmentation fault error.

我如何解决这个问题? 和/或,什么是最佳的解冻方式? 由于规模大,请附上该法典的一部分。 我将努力将该项目添加到Gite Hub:

样本使用

# segmenter --i out.ts --l 10 --o stream.m3u8 --d segments --f stream

文件

FFLIBS=`pkg-config --libs libavformat libavcodec libavutil`
FFFLAGS=`pkg-config --cflags libavformat libavcodec libavutil`

all:
    gcc -Wall -g 页: 1 -o segmenter ${FFFLAGS} ${FFLIBS}

页: 1

/*
 * Copyright (c) 2009 Chase Douglas
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include "libavformat/avformat.h"

#include "libavformat/avio.h"

#include <sys/stat.h>

#include "segmenter.h"
#include "libavformat/avformat.h"

#define IMAGE_ID3_SIZE 9171

void printUsage() {
    fprintf(stderr, "
Example: segmenter --i infile --d baseDir --f baseFileName --o playListFile.m3u8 --l 10 
");
    fprintf(stderr, "
Options: 
");
    fprintf(stderr, "--i <infile>.
");
    fprintf(stderr, "--o <outfile>.
");
    fprintf(stderr, "--d basedir, the base directory for files.
");
    fprintf(stderr, "--f baseFileName, output files will be baseFileName-#.
");
    fprintf(stderr, "--l segment length, the length of each segment.
");
    fprintf(stderr, "--a,  audio only decode for < 64k streams.
");
    fprintf(stderr, "--v,  video only decode for < 64k streams.
");
    fprintf(stderr, "--version, print version details and exit.
");
    fprintf(stderr, "

");
}

void ffmpeg_version() {
    // output build and version numbers
    fprintf(stderr, "  libavutil version:   %s
", AV_STRINGIFY(LIBAVUTIL_VERSION));
    fprintf(stderr, "  libavutil build:     %d
", LIBAVUTIL_BUILD);
    fprintf(stderr, "  libavcodec version:  %s
", AV_STRINGIFY(LIBAVCODEC_VERSION));
    fprintf(stdout, "  libavcodec build:    %d
", LIBAVCODEC_BUILD);
    fprintf(stderr, "  libavformat version: %s
", AV_STRINGIFY(LIBAVFORMAT_VERSION));
    fprintf(stderr, "  libavformat build:   %d
", LIBAVFORMAT_BUILD);
    fprintf(stderr, "  built on " __DATE__ " " __TIME__);
#ifdef __GNUC__
    fprintf(stderr, ", gcc: " __VERSION__ "
");
#else
    fprintf(stderr, ", using a non-gcc compiler
");
#endif
}


static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStream *input_stream) {
    AVCodecContext *input_codec_context;
    AVCodecContext *output_codec_context;
    AVStream *output_stream;

    output_stream = avformat_new_stream(output_format_context, 0);
    if (!output_stream) {
        fprintf(stderr, "Segmenter error: Could not allocate stream
");
        exit(1);
    }

    input_codec_context = input_stream->codec;
    output_codec_context = output_stream->codec;

    output_codec_context->codec_id = input_codec_context->codec_id;
    output_codec_context->codec_type = input_codec_context->codec_type;
    output_codec_context->codec_tag = input_codec_context->codec_tag;
    output_codec_context->bit_rate = input_codec_context->bit_rate;
    output_codec_context->extradata = input_codec_context->extradata;
    output_codec_context->extradata_size = input_codec_context->extradata_size;

    if (av_q2d(input_codec_context->time_base) * input_codec_context->ticks_per_frame > av_q2d(input_stream->time_base) && av_q2d(input_stream->time_base) < 1.0 / 1000) {
        output_codec_context->time_base = input_codec_context->time_base;
        output_codec_context->time_base.num *= input_codec_context->ticks_per_frame;
    } else {
        output_codec_context->time_base = input_stream->time_base;
    }

    switch (input_codec_context->codec_type) {
#ifdef USE_OLD_FFMPEG
        case CODEC_TYPE_AUDIO:
#else
        case AVMEDIA_TYPE_AUDIO:
#endif
            output_codec_context->channel_layout = input_codec_context->channel_layout;
            output_codec_context->sample_rate = input_codec_context->sample_rate;
            output_codec_context->channels = input_codec_context->channels;
            output_codec_context->frame_size = input_codec_context->frame_size;
            if ((input_codec_context->block_align == 1 && input_codec_context->codec_id == CODEC_ID_MP3) || input_codec_context->codec_id == CODEC_ID_AC3) {
                output_codec_context->block_align = 0;
            } else {
                output_codec_context->block_align = input_codec_context->block_align;
            }
            break;
#ifdef USE_OLD_FFMPEG
        case CODEC_TYPE_VIDEO:
#else
        case AVMEDIA_TYPE_VIDEO:
#endif
            output_codec_context->pix_fmt = input_codec_context->pix_fmt;
            output_codec_context->width = input_codec_context->width;
            output_codec_context->height = input_codec_context->height;
            output_codec_context->has_b_frames = input_codec_context->has_b_frames;

            if (output_format_context->oformat->flags & AVFMT_GLOBALHEADER) {
                output_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
            }
            break;
        default:
            break;
    }

    return output_stream;
}

int write_index_file(const char index[], const char tmp_index[], const unsigned int planned_segment_duration, const unsigned int actual_segment_duration[],
        const char output_directory[], const char output_prefix[], const char output_file_extension[],
        const unsigned int first_segment, const unsigned int last_segment) {
    FILE *index_fp;
    char *write_buf;
    unsigned int i;

    index_fp = fopen(tmp_index, "w");
    if (!index_fp) {
        fprintf(stderr, "Could not open temporary m3u8 index file (%s), no index file will be created
", tmp_index);
        return -1;
    }

    write_buf = malloc(sizeof (char) * 1024);
    if (!write_buf) {
        fprintf(stderr, "Could not allocate write buffer for index file, index file will be invalid
");
        fclose(index_fp);
        return -1;
    }

    unsigned int maxDuration = planned_segment_duration;

    for (i = first_segment; i <= last_segment; i++)
        if (actual_segment_duration[i] > maxDuration)
            maxDuration = actual_segment_duration[i];



    snprintf(write_buf, 1024, "#EXTM3U
#EXT-X-TARGETDURATION:%u
", maxDuration);

    if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {
        fprintf(stderr, "Could not write to m3u8 index file, will not continue writing to index file
");
        free(write_buf);
        fclose(index_fp);
        return -1;
    }

    for (i = first_segment; i <= last_segment; i++) {
        snprintf(write_buf, 1024, "#EXTINF:%u,
%s-%u%s
", actual_segment_duration[i], output_prefix, i, output_file_extension);
        if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {
            fprintf(stderr, "Could not write to m3u8 index file, will not continue writing to index file
");
            free(write_buf);
            fclose(index_fp);
            return -1;
        }
    }

    snprintf(write_buf, 1024, "#EXT-X-ENDLIST
");
    if (fwrite(write_buf, strlen(write_buf), 1, index_fp) != 1) {
        fprintf(stderr, "Could not write last file and endlist tag to m3u8 index file
");
        free(write_buf);
        fclose(index_fp);
        return -1;
    }

    free(write_buf);
    fclose(index_fp);

    return rename(tmp_index, index);
}

int main(int argc, const char *argv[]) {
    //input parameters
    char inputFilename[MAX_FILENAME_LENGTH], playlistFilename[MAX_FILENAME_LENGTH], baseDirName[MAX_FILENAME_LENGTH], baseFileName[MAX_FILENAME_LENGTH];
    char baseFileExtension[5]; //either "ts", "aac" or "mp3"
    int segmentLength, outputStreams, verbosity, version;



    char currentOutputFileName[MAX_FILENAME_LENGTH];
    char tempPlaylistName[MAX_FILENAME_LENGTH];


    //these are used to determine the exact length of the current segment
    double prev_segment_time = 0;
    double segment_time;
    unsigned int actual_segment_durations[2048];
    double packet_time = 0;

    //new variables to keep track of output size
    double output_bytes = 0;

    unsigned int output_index = 1;
    AVOutputFormat *ofmt;
    AVFormatContext *ic = NULL;
    AVFormatContext *oc;
    AVStream *video_st = NULL;
    AVStream *audio_st = NULL;
    AVCodec *codec;
    int video_index;
    int audio_index;
    unsigned int first_segment = 1;
    unsigned int last_segment = 0;
    int write_index = 1;
    int decode_done;
    int ret;
    int i;

    unsigned char id3_tag[128];
    unsigned char * image_id3_tag;

    size_t id3_tag_size = 73;
    int newFile = 1; //a boolean value to flag when a new file needs id3 tag info in it

    if (parseCommandLine(inputFilename, playlistFilename, baseDirName, baseFileName, baseFileExtension, &outputStreams, &segmentLength, &verbosity, &version, argc, argv) != 0)
        return 0;

    if (version) {
        ffmpeg_version();
        return 0;
    }


    fprintf(stderr, "%s %s
", playlistFilename, tempPlaylistName);


    image_id3_tag = malloc(IMAGE_ID3_SIZE);
    if (outputStreams == OUTPUT_STREAM_AUDIO)
        build_image_id3_tag(image_id3_tag);
    build_id3_tag((char *) id3_tag, id3_tag_size);

    snprintf(tempPlaylistName, strlen(playlistFilename) + strlen(baseDirName) + 1, "%s%s", baseDirName, playlistFilename);
    strncpy(playlistFilename, tempPlaylistName, strlen(tempPlaylistName));
    strncpy(tempPlaylistName, playlistFilename, MAX_FILENAME_LENGTH);
    strncat(tempPlaylistName, ".", 1);

    //decide if this is an aac file or a mpegts file.
    //postpone deciding format until later
    /*    ifmt = av_find_input_format("mpegts");
    if (!ifmt)
    {
    fprintf(stderr, "Could not find MPEG-TS demuxer.
");
    exit(1);
    } */

    av_log_set_level(AV_LOG_DEBUG);

    av_register_all();
    ret = avformat_open_input(&ic, inputFilename, NULL, NULL);
    if (ret != 0) {
        fprintf(stderr, "Could not open input file %s. Error %d.
", inputFilename, ret);
        exit(1);
    }

    if (avformat_find_stream_info(ic, NULL) < 0) {
        fprintf(stderr, "Could not read stream information.
");
        exit(1);
    }

    oc = avformat_alloc_context();
    if (!oc) {
        fprintf(stderr, "Could not allocate output context.");
        exit(1);
    }

    video_index = -1;
    audio_index = -1;

    for (i = 0; i < ic->nb_streams && (video_index < 0 || audio_index < 0); i++) {
        switch (ic->streams[i]->codec->codec_type) {

#ifdef USE_OLD_FFMPEG
            case CODEC_TYPE_VIDEO:
#else
            case AVMEDIA_TYPE_VIDEO:
#endif
                video_index = i;
                ic->streams[i]->discard = AVDISCARD_NONE;
                if (outputStreams & OUTPUT_STREAM_VIDEO)
                    video_st = add_output_stream(oc, ic->streams[i]);
                break;
#ifdef USE_OLD_FFMPEG
            case CODEC_TYPE_AUDIO:
#else
            case AVMEDIA_TYPE_AUDIO:
#endif
                audio_index = i;
                ic->streams[i]->discard = AVDISCARD_NONE;
                if (outputStreams & OUTPUT_STREAM_AUDIO)
                    audio_st = add_output_stream(oc, ic->streams[i]);
                break;
            default:
                ic->streams[i]->discard = AVDISCARD_ALL;
                break;
        }
    }

    if (video_index == -1) {
        fprintf(stderr, "Stream must have video component.
");
        exit(1);
    }

    //now that we know the audio and video output streams
    //we can decide on an output format.
    if (outputStreams == OUTPUT_STREAM_AUDIO) {
        //the audio output format should be the same as the audio input format
        switch (ic->streams[audio_index]->codec->codec_id) {
            case CODEC_ID_MP3:
                fprintf(stderr, "Setting output audio to mp3.");
                strncpy(baseFileExtension, ".mp3", strlen(".mp3"));
                ofmt = av_guess_format("mp3", NULL, NULL);
                break;
            case CODEC_ID_AAC:
                fprintf(stderr, "Setting output audio to aac.");
                ofmt = av_guess_format("adts", NULL, NULL);
                break;
            default:
                fprintf(stderr, "Codec id %d not supported.
", ic->streams[audio_index]->id);
        }
        if (!ofmt) {
            fprintf(stderr, "Could not find audio muxer.
");
            exit(1);
        }
    } else {
        ofmt = av_guess_format("mpegts", NULL, NULL);
        if (!ofmt) {
            fprintf(stderr, "Could not find MPEG-TS muxer.
");
            exit(1);
        }
    }
    oc->oformat = ofmt;

    if (outputStreams & OUTPUT_STREAM_VIDEO && oc->oformat->flags & AVFMT_GLOBALHEADER) {
        oc->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }


    /*  Deprecated: pass the options to avformat_write_header directly.
        if (av_set_parameters(oc, NULL) < 0) {
            fprintf(stderr, "Invalid output format parameters.
");
            exit(1);
        }
     */

    av_dump_format(oc, 0, baseFileName, 1);


    //open the video codec only if there is video data
    if (video_index != -1) {
        if (outputStreams & OUTPUT_STREAM_VIDEO)
            codec = avcodec_find_decoder(video_st->codec->codec_id);
        else
            codec = avcodec_find_decoder(ic->streams[video_index]->codec->codec_id);
        if (!codec) {
            fprintf(stderr, "Could not find video decoder, key frames will not be honored.
");
        }

        if (outputStreams & OUTPUT_STREAM_VIDEO)
            ret = avcodec_open2(video_st->codec, codec, NULL);
        else
            avcodec_open2(ic->streams[video_index]->codec, codec, NULL);
        if (ret < 0) {
            fprintf(stderr, "Could not open video decoder, key frames will not be honored.
");
        }
    }

    snprintf(currentOutputFileName, strlen(baseDirName) + strlen(baseFileName) + strlen(baseFileExtension) + 10, "%s%s-%u%s", baseDirName, baseFileName, output_index++, baseFileExtension);

    if (avio_open(&oc->pb, currentOutputFileName, URL_WRONLY) < 0) {
        fprintf(stderr, "Could not open  %s .
", currentOutputFileName);
        exit(1);
    }
    newFile = 1;

    int r = avformat_write_header(oc,NULL);
    if (r) {
        fprintf(stderr, "Could not write mpegts header to first output file.
");
        debugReturnCode(r);
        exit(1);
    }

    //no segment info is written here. This just creates the shell of the playlist file
    write_index = !write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);

    do {
        AVPacket packet;

        decode_done = av_read_frame(ic, &packet);

        if (decode_done < 0) {
            break;
        }

        if (av_dup_packet(&packet) < 0) {
            fprintf(stderr, "Could not duplicate packet.");
            av_free_packet(&packet);
            break;
        }

        //this time is used to check for a break in the segments
        //    if (packet.stream_index == video_index && (packet.flags & PKT_FLAG_KEY))
        //    {
        //    segment_time = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
        //    }
#if USE_OLD_FFMPEG
        if (packet.stream_index == video_index && (packet.flags & PKT_FLAG_KEY))
#else
        if (packet.stream_index == video_index && (packet.flags & AV_PKT_FLAG_KEY))
#endif
        {
            segment_time = (double) packet.pts * ic->streams[video_index]->time_base.num / ic->streams[video_index]->time_base.den;
        }
        //  else if (video_index < 0)
        //    {
        //        segment_time = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
        //    }

        //get the most recent packet time
        //this time is used when the time for the final segment is printed. It may not be on the edge of
        //of a keyframe!
        if (packet.stream_index == video_index)
            packet_time = (double) packet.pts * ic->streams[video_index]->time_base.num / ic->streams[video_index]->time_base.den; //(double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
        else if (outputStreams & OUTPUT_STREAM_AUDIO)
            packet_time = (double) audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
        else
            continue;
        //start looking for segment splits for videos one half second before segment duration expires. This is because the
        //segments are split on key frames so we cannot expect all segments to be split exactly equally.
        if (segment_time - prev_segment_time >= segmentLength - 0.5) {
            fprintf(stderr, "looking to print index file at time %lf
", segment_time);
            avio_flush(oc->pb);
            avio_close(oc->pb);

            if (write_index) {
                actual_segment_durations[++last_segment] = (unsigned int) rint(segment_time - prev_segment_time);
                write_index = !write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);
                fprintf(stderr, "Writing index file at time %lf
", packet_time);
            }

            struct stat st;
            stat(currentOutputFileName, &st);
            output_bytes += st.st_size;

            snprintf(currentOutputFileName, strlen(baseDirName) + strlen(baseFileName) + strlen(baseFileExtension) + 10, "%s%s-%u%s", baseDirName, baseFileName, output_index++, baseFileExtension);
            if (avio_open(&oc->pb, currentOutputFileName, URL_WRONLY) < 0) {
                fprintf(stderr, "Could not open  %s 
", currentOutputFileName);
                break;
            }

            newFile = 1;
            prev_segment_time = segment_time;
        }

        if (outputStreams == OUTPUT_STREAM_AUDIO && packet.stream_index == audio_index) {
            if (newFile && outputStreams == OUTPUT_STREAM_AUDIO) {
                //add id3 tag info
                //fprintf(stderr, "adding id3tag to file %s
", currentOutputFileName);
                //printf("%lf %lld %lld %lld %lld %lld %lf
", segment_time, audio_st->pts.val, audio_st->cur_dts, audio_st->cur_pkt.pts, packet.pts, packet.dts, packet.dts * av_q2d(ic->streams[audio_index]->time_base) );
                fill_id3_tag((char*) id3_tag, id3_tag_size, packet.dts);
                avio_write(oc->pb, id3_tag, id3_tag_size);
                avio_write(oc->pb, image_id3_tag, IMAGE_ID3_SIZE);
                avio_flush(oc->pb);
                newFile = 0;
            }

            packet.stream_index = 0; //only one stream in audio only segments
            ret = av_interleaved_write_frame(oc, &packet);
        } else if (outputStreams & OUTPUT_STREAM_VIDEO) {
            if (newFile) {
                //fprintf(stderr, "New File: %lld %lld %lld
", packet.pts, video_st->pts.val, audio_st->pts.val);
                //printf("%lf %lld %lld %lld %lld %lld %lf
", segment_time, audio_st->pts.val, audio_st->cur_dts, audio_st->cur_pkt.pts, packet.pts, packet.dts, packet.dts * av_q2d(ic->streams[audio_index]->time_base) );
                newFile = 0;
            }
            if (outputStreams == OUTPUT_STREAM_VIDEO)
                ret = av_write_frame(oc, &packet);
            else
                ret = av_interleaved_write_frame(oc, &packet);
        }

        if (ret < 0) {
            fprintf(stderr, "Warning: Could not write frame of stream.
");
        } else if (ret > 0) {
            fprintf(stderr, "End of stream requested.
");
            av_free_packet(&packet);
            break;
        }

        av_free_packet(&packet);
    } while (!decode_done);

    //make sure all packets are written and then close the last file.
    avio_flush(oc->pb);
    av_write_trailer(oc);

    if (video_st && video_st->codec)
        avcodec_close(video_st->codec);

    if (audio_st && audio_st->codec)
        avcodec_close(audio_st->codec);

    for (i = 0; i < oc->nb_streams; i++) {
        av_freep(&oc->streams[i]->codec);
        av_freep(&oc->streams[i]);
    }

    avio_close(oc->pb);
    av_free(oc);

    struct stat st;
    stat(currentOutputFileName, &st);
    output_bytes += st.st_size;


    if (write_index) {
        actual_segment_durations[++last_segment] = (unsigned int) rint(packet_time - prev_segment_time);

        //make sure that the last segment length is not zero
        if (actual_segment_durations[last_segment] == 0)
            actual_segment_durations[last_segment] = 1;

        write_index_file(playlistFilename, tempPlaylistName, segmentLength, actual_segment_durations, baseDirName, baseFileName, baseFileExtension, first_segment, last_segment);

    }

    write_stream_size_file(baseDirName, baseFileName, output_bytes * 8 / segment_time);

    return 0;
}
最佳回答

你们尝试了什么初步的欺骗措施? 您的法典是否以 g子或gger子操作,以发现其坠毁的一条线? 或者至少是增加打印说明,看看它在多大程度上在坠毁之前在你的节目中?

首先,在汇编者中用“-g”办法汇编你的来源,以增加伪造符号。 然后,根据 g子管理你的法典。

valgrind is another useful tool that might help you find where your program is crashing if it s touching invalid memory.

问题回答

暂无回答




相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签