记录器在尝试打开 ofstream 时收到分段错误
Logger receiving segmentation fault when trying to open ofstream
当我尝试为 Logger class 打开文件时抛出的一些 SIGSEGV 遇到了一些麻烦。我已经使用这个 class 一段时间了,但这是我第一次得到这个。从像以前这样的简单行开始:
LOG(logDEBUG) << "Node " << nodeId << " in link layer state waitAck.";
我从 strace 得到这个:
open("simulation.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
lseek(3, 0, SEEK_END) = 16380108
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
得到这个 gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7210289 in malloc_consolidate () from /usr/lib/libc.so.6
(gdb) backtrace
#0 0x00007ffff7210289 in malloc_consolidate () from /usr/lib/libc.so.6
#1 0x00007ffff7211d2a in _int_malloc () from /usr/lib/libc.so.6
#2 0x00007ffff7213d44 in malloc () from /usr/lib/libc.so.6
#3 0x00007ffff7ae1a48 in operator new (sz=8192)
at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50
#4 0x00007ffff7ae1af5 in operator new[] (sz=<optimized out>)
at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_opv.cc:32
#5 0x00007ffff7b41698 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer
(this=0x7fffffffdc68)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
#6 0x00007ffff7b45932 in std::basic_filebuf<char, std::char_traits<char> >::open (this=0x7fffffffdc68,
__s=0x690550 <Log::fileName[abi:cxx11]+16> "simulation.log", __mode=17)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:187
#7 0x00007ffff7b45a53 in std::basic_filebuf<char, std::char_traits<char> >::open (
__mode=<optimized out>, __s=..., this=0x7fffffffdc68)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:308
#8 std::basic_ofstream<char, std::char_traits<char> >::open (this=0x7fffffffdc60, __s=...,
__mode=<optimized out>)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:823
#9 0x0000000000421c33 in Log::Log (this=0x7fffffffdc60) at src/log.cpp:21
#10 0x0000000000446198 in LinkCsma::iterate2Receive (this=0x6a9440, t=@0x7fffffffe1fc: 9387)
at src/link_csma.cpp:329
#11 0x00000000004232a4 in Node::iterate2Receive (this=0x6a52f0, t=@0x7fffffffe1fc: 9387)
at src/node.cpp:550
#12 0x000000000042f2bc in DirectionalNodes::iterate (this=0x6a6eb0, t=@0x7fffffffe1fc: 9387)
at src/directional_nodes.cpp:250
#13 0x0000000000460ce5 in Simulation::run (this=0x6a6f00) at src/simulation.cpp:184
#14 0x0000000000429e8c in main (argc=1, argv=0x7fffffffe878) at src/main.cpp:65
日志中的代码 class 是:
#ifndef LOG_H__
#define LOG_H__
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio>
#include <ctime>
#ifdef DEBUG
#define LOG(level) \
Log().write(level)
#else
#define LOG(level) \
if(level >= logDEBUG) ; \
else Log().write(level)
#endif
enum LogLevel {
logERROR,
logWARNING,
logINFO,
logDEBUG
};
class Log
{
public:
Log();
~Log();
static void setFile(const std::string& s);
std::ofstream& write(LogLevel level = logINFO);
protected:
std::ofstream fileStream;
private:
Log(const Log&);
Log& operator =(const Log&);
std::string level2String(LogLevel level);
std::string timeString();
static std::string fileName;
static const std::string DEFAULT_LOG_FILE;
};
#endif //LOG_H__
并且:
#include "../include/log.h"
using namespace std;
string Log::fileName;
const string Log::DEFAULT_LOG_FILE = "logfile.log";
Log::Log()
{
fileStream.open(fileName, ios::out | ios::app);
}
Log::~Log()
{
fileStream << endl;
flush(fileStream);
fileStream.close();
}
std::string Log::level2String(LogLevel level)
{
static const char* const buffer[] = { "ERROR", "WARNING", "INFO", "DEBUG" };
return buffer[level];
}
void Log::setFile(const std::string& s)
{
fileName = s;
}
std::string Log::timeString()
{
time_t t = time(0);
struct tm * now = localtime(&t);
stringstream ss;
ss << now->tm_hour << ":" << now->tm_min << " "
<< now->tm_mday << "/" << (now->tm_mon+1) << "/" << (now->tm_year+1900);
return ss.str();
}
std::ofstream& Log::write(LogLevel level)
{
fileStream << timeString();
fileStream << " " << level2String(level) << ":\t";
return fileStream;
}
似乎我通过将输出从 ofstream 更改为 FILE* 并在使用 fprintf 写入 FILE* 之前使用 ostringstream 作为缓冲区来解决它。如图http://www.drdobbs.com/cpp/logging-in-c/201804215.
当我尝试为 Logger class 打开文件时抛出的一些 SIGSEGV 遇到了一些麻烦。我已经使用这个 class 一段时间了,但这是我第一次得到这个。从像以前这样的简单行开始:
LOG(logDEBUG) << "Node " << nodeId << " in link layer state waitAck.";
我从 strace 得到这个:
open("simulation.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
lseek(3, 0, SEEK_END) = 16380108
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
得到这个 gdb:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7210289 in malloc_consolidate () from /usr/lib/libc.so.6
(gdb) backtrace
#0 0x00007ffff7210289 in malloc_consolidate () from /usr/lib/libc.so.6
#1 0x00007ffff7211d2a in _int_malloc () from /usr/lib/libc.so.6
#2 0x00007ffff7213d44 in malloc () from /usr/lib/libc.so.6
#3 0x00007ffff7ae1a48 in operator new (sz=8192)
at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50
#4 0x00007ffff7ae1af5 in operator new[] (sz=<optimized out>)
at /build/gcc/src/gcc/libstdc++-v3/libsupc++/new_opv.cc:32
#5 0x00007ffff7b41698 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer
(this=0x7fffffffdc68)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
#6 0x00007ffff7b45932 in std::basic_filebuf<char, std::char_traits<char> >::open (this=0x7fffffffdc68,
__s=0x690550 <Log::fileName[abi:cxx11]+16> "simulation.log", __mode=17)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:187
#7 0x00007ffff7b45a53 in std::basic_filebuf<char, std::char_traits<char> >::open (
__mode=<optimized out>, __s=..., this=0x7fffffffdc68)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:308
#8 std::basic_ofstream<char, std::char_traits<char> >::open (this=0x7fffffffdc60, __s=...,
__mode=<optimized out>)
at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:823
#9 0x0000000000421c33 in Log::Log (this=0x7fffffffdc60) at src/log.cpp:21
#10 0x0000000000446198 in LinkCsma::iterate2Receive (this=0x6a9440, t=@0x7fffffffe1fc: 9387)
at src/link_csma.cpp:329
#11 0x00000000004232a4 in Node::iterate2Receive (this=0x6a52f0, t=@0x7fffffffe1fc: 9387)
at src/node.cpp:550
#12 0x000000000042f2bc in DirectionalNodes::iterate (this=0x6a6eb0, t=@0x7fffffffe1fc: 9387)
at src/directional_nodes.cpp:250
#13 0x0000000000460ce5 in Simulation::run (this=0x6a6f00) at src/simulation.cpp:184
#14 0x0000000000429e8c in main (argc=1, argv=0x7fffffffe878) at src/main.cpp:65
日志中的代码 class 是:
#ifndef LOG_H__
#define LOG_H__
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio>
#include <ctime>
#ifdef DEBUG
#define LOG(level) \
Log().write(level)
#else
#define LOG(level) \
if(level >= logDEBUG) ; \
else Log().write(level)
#endif
enum LogLevel {
logERROR,
logWARNING,
logINFO,
logDEBUG
};
class Log
{
public:
Log();
~Log();
static void setFile(const std::string& s);
std::ofstream& write(LogLevel level = logINFO);
protected:
std::ofstream fileStream;
private:
Log(const Log&);
Log& operator =(const Log&);
std::string level2String(LogLevel level);
std::string timeString();
static std::string fileName;
static const std::string DEFAULT_LOG_FILE;
};
#endif //LOG_H__
并且:
#include "../include/log.h"
using namespace std;
string Log::fileName;
const string Log::DEFAULT_LOG_FILE = "logfile.log";
Log::Log()
{
fileStream.open(fileName, ios::out | ios::app);
}
Log::~Log()
{
fileStream << endl;
flush(fileStream);
fileStream.close();
}
std::string Log::level2String(LogLevel level)
{
static const char* const buffer[] = { "ERROR", "WARNING", "INFO", "DEBUG" };
return buffer[level];
}
void Log::setFile(const std::string& s)
{
fileName = s;
}
std::string Log::timeString()
{
time_t t = time(0);
struct tm * now = localtime(&t);
stringstream ss;
ss << now->tm_hour << ":" << now->tm_min << " "
<< now->tm_mday << "/" << (now->tm_mon+1) << "/" << (now->tm_year+1900);
return ss.str();
}
std::ofstream& Log::write(LogLevel level)
{
fileStream << timeString();
fileStream << " " << level2String(level) << ":\t";
return fileStream;
}
似乎我通过将输出从 ofstream 更改为 FILE* 并在使用 fprintf 写入 FILE* 之前使用 ostringstream 作为缓冲区来解决它。如图http://www.drdobbs.com/cpp/logging-in-c/201804215.