c++ - 运行良好,但在完成之前崩溃

标签 c++ ubuntu boost

<分区>

我用 OpenCV 和 boost 用 c++ 编写了一个应用程序,它运行良好且正确,但在退出之前它崩溃了(如果我逐步调试,当 return 0; 在main) 结尾说:

  • 在 kdevelop 中:

    *** Error in `/home/xxx/git_repos/my_proj/build/my_proj': free(): invalid pointer: 0x00000000008939c0 ***
    *** Crashed with return code: 0 ***
    
  • 在命令行中:

    *** Error in `./my_proj': free(): invalid pointer: 0x00000000008939c0 ***
    Aborted (core dumped)
    
  • 如果我使用 gdb:

    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    *** Error in `/home/xxx/git_repos/my_proj/build/plate_info_extractor': free(): invalid pointer: 0x00000000008939c0 ***
    
    Program received signal SIGABRT, Aborted.
    0x00007ffff5b83cc9 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
    56  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
    

有什么帮助吗?我不知道哪里出了问题。


我已经评论了一些代码部分,看来问题出在我用来记录错误/信息的代码中......所以:

#include "CLogger.hpp"

static void help(const std::string& appNameIn)
{
    std::cerr << "Usage: " << appNameIn << " <option(s)> SOURCES" << std::endl
        << "Options:" << std::endl
        << "  -h,--help                     Show this help message" << std::endl
        << "  -c,--config CONFIG FILE       Specify the name and path to the config file" << std::endl
        << std::endl
        << std::endl;
}

enum RetVals
{
    NO_ERRORS,
    NOT_ENOUGH_PARAMETERS,
    UNKNOWN_OPTION,
    SHOW_USAGE,
    UNKNOWN_EXCEPTION,
    OTHER_EXCEPTION,
};

int main(int argc, char **argv)
{
    Logger::initFilesList();
    Logger::initLogging();

    BoostLogger lg = setClassNameAttribute("main");

    if (argc == 3)
    {
        std::string opt = argv[1];
        if (opt == "-c" || opt == "--config")
        {
            try
            {
                std::cout << "running" << std::endl;
            }
            catch (std::exception& e)
            {
                BOOST_LOG_SEV(lg, Logger::SeverityLevels::error) << "Other exception: " << e.what();
                return OTHER_EXCEPTION;
            }
            catch (...)
            {
                BOOST_LOG_SEV(lg, Logger::SeverityLevels::error) << "Unkown exception ...";
                return UNKNOWN_EXCEPTION;
            }
        }
        else
        {
            help(argv[0]);
            BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "The options are -c or --config, -h or --help";
            return UNKNOWN_OPTION;
        }
    }
    else if (argc == 2 && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help"))
    {
        help(argv[0]);
        BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "Call help function";
        return SHOW_USAGE;
    }
    else
    {
        help(argv[0]);
        BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "The number of input parameters is wrong";
        return NOT_ENOUGH_PARAMETERS;
    }

    return NO_ERRORS;
}

和 CLogger.hpp:

#pragma once

#include <list>
#include <string>

#include <boost/log/common.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/concept_check.hpp>

#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

class Logger
{
private:
    static std::list< std::string > sm_logFilesList;

    static const std::string sm_folderOfLogFiles;

    /** the function adds the input log file to the list
     * 
     * @param logFilePathIn : input log file path
     */
    static void addNewLogFileToList(const std::string& logFilePathIn, bool sorting = false);

    /** The function adds new logs to new log file and remove the oltest ones to have always 2 log files */
    static void addNewRemoveOldLogs(bool sorting = false);

    /** @returns : if the input path is valid or not */
    static bool checkPath(const boost::filesystem::path& pathIn);

    /** @returns if the file with the first input path was more recent accesed than the file with the second input path
     */
    static bool compareAccessTime(const std::string& path1In, const std::string& path2In);

    /** The function remove the old log files and keeps just the most recent two */
    static void removeOldLogFiles();

    /** The function is calles at the end of each file and removes the old files keeping just the last two */
    static void openingHandler(boost::log::sinks::text_file_backend::stream_type& file);

public:
    enum SeverityLevels
    {
        debug,
        info,
        warning,
        error
    };

    /** The function sets the sm_logFilesList to contain the files if there are log files from earlier runs */
    static void initFilesList();

    /** The fuction is initializing the sinks and the formatter of the logger */
    static void initLogging();
};

typedef boost::log::sources::severity_logger< Logger::SeverityLevels > BoostLogger;

    /** the overloaded << operator of the BoostLogger */
    std::ostream& operator<< (std::ostream& strm, Logger::SeverityLevels level);

/** The function sets the logger attribute ClassName to the specified string and returns the initialized logger
* 
* @param classNameIn : input string name of the class
* 
* @returns : initialized BoostLogger
*/
BoostLogger setClassNameAttribute(const std::string& classNameIn);

和实现:

#include "CLogger.hpp"

#include <boost/log/attributes.hpp>
#include <boost/log/attributes/current_process_id.hpp>
#include <boost/log/attributes/current_process_name.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/file.hpp>

typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > SinkTextFileBakend;

BOOST_LOG_ATTRIBUTE_KEYWORD(correlid, "CorrelationID", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", Logger::SeverityLevels)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(threadid, "ThreadID", boost::log::attributes::current_thread_id)
BOOST_LOG_ATTRIBUTE_KEYWORD(classname, "ClassName", std::string)

std::list< std::string > Logger::sm_logFilesList;

const std::string Logger::sm_folderOfLogFiles = "../logs/";

std::ostream& operator<<(std::ostream& strm, Logger::SeverityLevels level)
{
    static const char* strings[] =
    {
        "DEBUG",
        "INFO",
        "WARN",
        "ERROR"
    };

    if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
        strm << strings[level];
    else
        strm << static_cast< int >(level);

    return strm;
}

BoostLogger setClassNameAttribute(const std::string& classNameIn)
{
    BoostLogger lg;
    lg.add_attribute("ClassName", boost::log::attributes::constant<std::string>(classNameIn));
    return lg;
}

void Logger::removeOldLogFiles()
{
    while (sm_logFilesList.size() > 2)
    {
        std::string fileToDelete = sm_logFilesList.front();
        if (fs::exists(fs::path(fileToDelete)))
        {
            fs::remove(fs::path(fileToDelete));
            sm_logFilesList.pop_front();
        }
    }
}

bool Logger::compareAccessTime(const std::string& path1In, const std::string& path2In)
{
    return (fs::last_write_time(fs::path(path1In)) < fs::last_write_time(fs::path(path2In)));
}

void Logger::addNewLogFileToList(const std::string& logFilePathIn, bool sorting)
{
    if (std::find(sm_logFilesList.begin(), sm_logFilesList.end(), logFilePathIn) == sm_logFilesList.end())
    {
        sm_logFilesList.push_back(logFilePathIn);
        if (sorting)
        {
            sm_logFilesList.sort(compareAccessTime);
        }
        removeOldLogFiles();
    }
}

void Logger::addNewRemoveOldLogs(bool sorting)
{
    fs::path path(sm_folderOfLogFiles);
    fs::directory_iterator endDir;
    if (checkPath(path))
    { 
        for (fs::directory_iterator it(path); it != endDir; it++)
        {
            if (fs::is_regular_file(it->status()))
            {
                if (fs::extension(*it) == ".log")
                {
                    std::string fileToPush = it->path().string();
                    addNewLogFileToList(fileToPush, sorting);
                }
            }
        }
    }
}

bool Logger::checkPath(const boost::filesystem::path& pathIn)
{
    if (!fs::exists(pathIn))
    {
        return false;
    }
    if (!fs::is_directory(pathIn))
    {
        return false;
    }

    return true;
}

void Logger::openingHandler(boost::log::sinks::text_file_backend::stream_type& file)
{
    addNewRemoveOldLogs();
}

void Logger::initFilesList()
{
    addNewRemoveOldLogs(true);
}

void Logger::initLogging()
{
    // Create a backend
    boost::shared_ptr< SinkTextFileBakend > sink = boost::log::add_file_log(
        sm_folderOfLogFiles + "plate_info_extractor_%Y-%m-%d_%H-%M-%S.%N.log",
        boost::log::keywords::format = boost::log::expressions::stream
            << boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("Executable") << "("
            << boost::log::expressions::attr< boost::log::attributes::current_process_id::value_type >("ExeUID") << ") CID("
            << correlid << ") " << severity << "["
            << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
            << "] [" << boost::log::expressions::attr< boost::log::attributes::current_thread_id::value_type >("ThreadID")
            << "] " << classname << " - " << boost::log::expressions::smessage,
        boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
        boost::log::keywords::rotation_size = 2 * 1024 * 1024,
        boost::log::keywords::auto_flush = true
    );

    sink->locked_backend()->set_open_handler(&openingHandler);

    boost::log::core::get()->set_filter(severity >= SeverityLevels::info);
    boost::log::core::get()->add_sink(sink);

#ifdef DEBUGGING
    boost::shared_ptr< boost::log::sinks::text_ostream_backend > backend =
        boost::make_shared< boost::log::sinks::text_ostream_backend >();
    backend->add_stream(
        boost::shared_ptr< std::ostream >(&std::cout));

    // Enable auto-flushing after each log record written
    backend->auto_flush(true);

    // Wrap it into the frontend and register in the core.
    // The backend requires synchronization in the frontend.
    // for testing and printing log in sysout
    boost::shared_ptr< boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > > backend_sink(
        new boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend >(backend));

    backend_sink->set_formatter(
        boost::log::expressions::stream
        // line id will be written in hex, 8-digits, zero-filled
        << boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("Executable")
        << "(" << boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("ExeUID")
        << ") CID(" << correlid << ") " << severity << " ["
        << boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
        << "] [" << boost::log::expressions::attr< boost::log::attributes::current_thread_id::value_type >("ThreadID")
        << "] " << classname << " - " << boost::log::expressions::smessage);
    boost::log::core::get()->add_sink(backend_sink); // for testing and printing log in sysout
#endif
}

我希望现在有足够的信息:)

最佳答案

这一行:

backend->add_stream(boost::shared_ptr< std::ostream >(&std::cout));

我看起来很糟糕。您的程序将在退出时尝试删除 std::cout。 我不熟悉 Boost Log,所以我不知道如何为 std::cout 正确设置接收器。

作为Arpegius指出你应该使用 null_deleter 来避免删除。类似这样的事情:

backend->add_stream(boost::shared_ptr< std::ostream>(&std::cout, boost::null_deleter()));

关于c++ - 运行良好,但在完成之前崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29532515/

相关文章:

c++ - 带有示例的嵌入式 Google v8 内存泄漏

c - POSIX C 中的打开功能不起作用

macos - 远程端口转发 SSH 被视为从 127.0.0.1 访问的无效用户

python - 代码在 IDE 中有效,但在终端控制台中无效

c++ - 从 boost::intrusive::list 中删除给定的项目

c++ - 更改相邻顶点的值并删除自循环

c++ - 从排序的 std::vector 中删除除最后一个具有相同键的元素之外的所有元素的最简洁方法?

c++ - 将 char 指针数组传递给函数

C++ 打开一个文件并写入文件的任意位置

c++ - 使用 Boost 和 Eclipse 进行单元测试