log4cplus开源库使用

news2024/11/17 2:47:38

log4cplus 的github地址:https://github.com/log4cplus/log4cplus

下载链接:log4cplus - Browse /log4cplus-stable/2.0.7 at SourceForge.net

官方文档:log4cplus / Wiki / Home

1.log4cplus配置

(1)打开解决方案

打开Visual Studio,进入 log4cplus-2.x\msvc14目录下,运行log4cplus.sln解决方案。

(2)进行相应设置

编译log4cplus需要注意三点:

①解决方案的平台与目标程序一致,这里选择的是x64;

②版本也要与目标程序一致,这里选择的是release版本;

③属性里面的字符集和目标程序一致;

选择log4cplus项目,右键——>属性——>配置属性——>常规——>字符集,选择Unicode字符集,如下图所示。(log4cplus默认使用多字节字符集,而VS新建项目默认使用Unicode字符集,如果不修改此处,则后面新建项目使用生成的dll时需要手动修改新建的项目为多字节字符集,否则会报错,总之两边统一用一种即可)

编译完成后,会在log4cplus-2.x\msvc14\x64\bin.Release文件夹下生成我们需要的log4cplus.lib和log4cplus.dll两个文件(我编译的是release版),如下图所示。

(3)目标程序的配置

将log4cplus-2.0.x目录下的include文件夹拷贝到我们的目标程序文件夹中,这里面是我们需要的头文件;在目标程序的属性里面设置头文件的包含目录。

设置lib文件的库目录以及将lib文件填入附加依赖项,如下图所示。

将dll文件放到程序的根目录:如果运行的是VS放置到和*.vcxproj一个文件夹下,如果运行的是*.exe,则和*.exe放置到一个文件夹下。

右键——>属性——>链接器——>输入——>附加依赖项——>加入log4cplus.lib,如下图所示。

如果不添加上述附加依赖项,则需要在代码开头中添加如下代码:

#pragma comment(lib, "log4cplus.lib")

2.头文件

主要类说明:

类名

说明

Filter

过滤器,过滤输出消息

Layout

布局器,控制输出消息的格式

Appender

挂接器,与布局器和过滤器紧密配合,将特定格式的消息过滤后输出到所挂接的设备终端如屏幕,文件等

Logger

记录器,保存并跟踪对象日志信息变更的实体,当你需要对一个对象进行记录时,就需要生成一个logger。

Hierarchy

分类器,层次化的树型结构,用于对被记录信息的分类,层次中每一个节点维护一个logger的所有信息

LogLevel

优先权,包括TRACE, DEBUG, INFO, WARNING, ERROR, FATAL。

主要头文件如下:

#include <log4cplus/logger.h> //获取表示记录句柄
#include <log4cplus/loggingmacros.h>//这个头文件声明日志记录宏。除此之外,它还声明了若干个标准日志级别:FATAL, ERROR, WARN, INFO, DEBUG, TRACE
#include <log4cplus/configurator.h>//此头文件声明类 BasicConfigurator。
#include <log4cplus/initializer.h>//这个头文件声明类 Initializer。

在log4cplus2中,上述类都已经包含在头文件log4cplus.h中了,因此只需要包含该头文件即可:

#include <log4cplus/log4cplus.h>
3.初始化Initializer

实例化该类会初始化log4cplus Initializer:

log4cplus::Initializer initializer;

该类还维护一个引用计数。该类可以被实例化多次。当此引用计数达到零时,在的最后一个实例被销毁后,它会关闭log4cplus内部。在log4cplus解除初始化后,无法重新初始化。

log4cplus尝试使用其他一些方法关闭其内部。但是,这意味着在main()退出后不能使用它。

4.基本配置BasicConfigurator
log4cplus::BasicConfigurator config;
config.configure();

这两行使用简单的布局配置根记录器。ConsoleAppender

log4cplus::Logger logger = log4cplus::Logger::getInstance(
LOG4CPLUS_TEXT("main"));

这里我们获得名为main的记录器的记录器句柄。上面使用的宏与Windows上的或宏具有相同的功能:如果定义了预处理器符号,它会在作为参数传递的字符串文字前面加上前缀,使其成为宽字符串文字。

LOG4CPLUS_WARN(logger, LOG4CPLUS_TEXT(“Hello, World!”));

这里我们调用宏来记录Hello,World!将消息输入主记录器。记录的消息将从主记录器传播到根记录器,根记录器连接了一个用于在控制台上打印的日志。在内部,这个宏使用C++字符串流来格式化hello, World!消息这样做的结果是,您可以使用所有标准的C++流操作器。

5.取消初始化

log4cplus试图取消初始化(deinitialize),并在退出后释放所有分配的资源。然而,同样,根据编译器、平台和运行时库的不同,这可能是不可能的。这就是为什么适当的去初始化是必要的。

在2.0及更高版本中,它由类的最后一个实例及其析构函数完成。在以前的版本中,调用是正确的关闭方法Logger::shutdown()

6.日志记录宏

宏在hood下使用C++字符串流。

7.日志级别

此示例显示了如何在运行时通过调整实例上的日志级别阈值来过滤日志消息。log4cplus的优先级由低到高:

  • NOT_SET_LOG_LEVEL:接受缺省的LogLevel,如果有父logger则继承它的LogLevel;
  • ALL_LOG_LEVEL:开放所有log信息输出
  • TRACE_LOG_LEVEL:开放trace信息输出(即ALL_LOG_LEVEL)
  • DEBUG_LOG_LEVEL:开放debug信息输出
  • INFO_LOG_LEVEL:开放info信息输出
  • WARN_LOG_LEVEL:开放warning信息输出
  • ERROR_LOG_LEVEL:开放error信息输出
  • FATAL_LOG_LEVEL:开放fatal信息输出
  • OFF_LOG_LEVEL:关闭所有log信息输出

各个logger可以通过setLogLevel设置自己的优先级,当某个logger的LogLevel设置成NOT_SET_LOG_LEVEL时,该logger会继承父logger的优先级,另外,如果定义了重名的多个logger, 对其中任何一个的修改都会同时改变其它logger。

代码示例:

#include <log4cplus/logger.h>
#include <log4cplus/loglevel.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>
#include <log4cplus/initializer.h>
#include <iomanip>
#include <iostream>

void printMessages(log4cplus::Logger const & logger)
{
        //使用所有常用日志级别打印信息
        LOG4CPLUS_TRACE(logger, "printMessages()");
        LOG4CPLUS_DEBUG(logger, "This is a DEBUG message");
        LOG4CPLUS_INFO(logger, "This is a INFO message");
        LOG4CPLUS_WARN(logger, "This is a WARN message");
        LOG4CPLUS_ERROR(logger, "This is a ERROR message");
        LOG4CPLUS_FATAL(logger, "This is a FATAL message");
}

void thresholdTest(log4cplus::LogLevel ll)
{
        log4cplus::Logger logger
 = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));

        //设置日志级别阈值
        logger.setLogLevel(ll);

            //打印信息
        //log4cplus::tcout << log4cplus::getLogLevelManager().toString(ll) << std::endl;

         printMessages(logger);


             std::cout << std::endl;
}

int main()
{
        //初始化
        log4cplus::Initializer initializer;
        //基本配置
        log4cplus::BasicConfigurator config;
        config.configure();

        thresholdTest(log4cplus::TRACE_LOG_LEVEL);//开放trace信息输出
        thresholdTest(log4cplus::DEBUG_LOG_LEVEL);//开放debug信息输出
        thresholdTest(log4cplus::INFO_LOG_LEVEL);//开放info信息输出
        thresholdTest(log4cplus::WARN_LOG_LEVEL);//开放warning信息输出
        thresholdTest(log4cplus::ERROR_LOG_LEVEL);//开放error信息输出
        thresholdTest(log4cplus::FATAL_LOG_LEVEL);//开放fatal信息输出

        return 0;
}
8.Appender输出位置

log4cplus默认将输出到控制台,提供ConsoleAppender用于操作。log4cplus还提供了三个类用于文件操作,它们是FileAppender类、RollingFileAppender类、DailyRollingFileAppender类。

Appender会注册到Logger中,Logger在写日志时,通过继承机制遍历所有注册到它本身和其父节点的Appender(在additivity为true的情况下),调用doAppend()方法,实现日志的写入。在doAppend方法中,若当前Appender注册了Filter,则doAppend还会判断当前日志时候通过了Filter的过滤,通过了Filter的过滤后,如果当前Appender继承自SkeletonAppender,还会检查当前日志级别时候要比当前Appender本身的日志级别阀门要打,所有这些都通过后,才会将LoggingEvent实例传递给Layout实例以格式化成一行日志信息,最后写入相应的目的地,在这些操作中,任何出现的错误都由ErrorHandler字段来处理。

(1)控制台输出ConsoleAppender

参考上文,输出在控制台中。

(2)文件输出FileAppender

FileAppender::FileAppender( const tstring& filename_,std::ios_base::openmode mode_, bool immediateFlush_,bool createDirs_)
  • filename:文件名;
  • mode:文件类型,可选择的文件类型包括app、ate、binary、in、out、trunc,因为实际上只是对stl的一个简单包装,这里就不多讲了。缺省是trunc,表示将先前文件删除;
  • immediateFlush:缓冲刷新标志,如果为true表示每向文件写一条记录就刷新一次缓存,否则直到FileAppender被关闭或文件缓存已满才更新文件,一般是要设置true的,比如你往文件写的过程中出现了错误(如程序非正常退出),即使文件没有正常关闭也可以保证程序终止时刻之前的所有记录都会被正常保存;
  • createDirs:是否创建目录;

输出在文件中,参考代码:

#include <log4cplus/log4cplus.h>

int main()
{
    //用Initializer类进行初始化
    log4cplus::Initializer initializer;

    //第1步:建立ConsoleAppender
    log4cplus::SharedAppenderPtr appender(new log4cplus::FileAppender(LOG4CPLUS_TEXT("E:\\test.log")));

    //第2步:设置Appender的名称和输出格式(SimpleLayout)
    appender->setName(LOG4CPLUS_TEXT("console"));

    log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");
    appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));

    //第3步:得到一个Logger实例,并设置其日志输出等级阈值
    log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));
    logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);

    //第4步:为Logger实例添加ConsoleAppender
    logger.addAppender(appender);

    //第5步:使用宏将日志输出
    LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));

    return 0;
}

同时输出到控制台和文件,代码示例:

#include <log4cplus/log4cplus.h>

int main()
{
    //用Initializer类进行初始化
    log4cplus::Initializer initializer;

    //第1步:建立ConsoleAppender
    log4cplus::SharedAppenderPtr consoleAppender(new log4cplus::ConsoleAppender);
    log4cplus::SharedAppenderPtr fileAppender(new log4cplus::FileAppender(LOG4CPLUS_TEXT("E:\\test.log")));

    //第2步:设置Appender的名称和输出格式(SimpleLayout)
    consoleAppender->setName(LOG4CPLUS_TEXT("console"));
    consoleAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::SimpleLayout()));

    fileAppender->setName(LOG4CPLUS_TEXT("console"));
    log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");
    fileAppender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));

    //第3步:得到一个Logger实例,并设置其日志输出等级阈值
    log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));
    logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);

    //第4步:为Logger实例添加ConsoleAppender
    logger.addAppender(consoleAppender);
    logger.addAppender(fileAppender);

    //第5步:使用宏将日志输出
    LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));

    return 0;
}

(4)RollingFileAppender

RollingFileAppender可以实现滚动转储的文件操作功能:

RollingFileAppender类可以根据你预先设定的大小来决定是否转储,当超过该大小,后续log信息会另存到新文件中,除了定义每个记录文件的大小之外,你还要确定在RollingFileAppender类对象构造时最多需要多少个这样的记录文件(maxBackupIndex+1),当存储的文件数目超过maxBackupIndex+1时,会删除最早生成的文件,保证整个文件数目等于maxBackupIndex+1。然后继续记录。

RollingFileAppender(
const log4cplus::tstring& filename,
long maxFileSize = 10*1024*1024, // 10 MB
int maxBackupIndex = 1,
bool immediateFlush = true,
bool createDirs = false);
  • filename:文件名;
  • maxFileSize:文件的最大尺寸;
  • maxBackupIndex:最大记录文件数;
  • immediateFlush:缓冲刷新标志;
  • createDirs:创建目录;

(4)DailyRollingFileAppender

DailyRollingFileAppender实现根据频度来决定是否转储的文件转储功能:

DailyRollingFileAppender类可以根据你预先设定的频度来决定是否转储,当超过该频度,后续log信息会另存到新文件中,这里的频度包括:MONTHLY(每月)、WEEKLY(每周)、DAILY(每日)、TWICE_DAILY(每两天)、HOURLY(每时)、MINUTELY(每分)。

需要指出的是这里的"频度"并不是你写入文件的速度,其实是否转储的标准并不依赖你写入文件的速度,而是依赖于写入的那一时刻是否满足了频度条件,即是否超过了以分钟、小时、周、月为单位的时间刻度,如果超过了就另存。

DailyRollingFileAppender(
const log4cplus::tstring& filename,
DailyRollingFileSchedule schedule = DAILY,
bool immediateFlush = true,
int maxBackupIndex = 10,
bool createDirs = false);
  • filename:文件名;
  • schedule:存储频度;
  • immediateFlush:缓冲刷新标志;
  • maxBackupIndex:最大记录文件数;
  • createDirs:创建目录

其中schedule为一个枚举类型,如下

enum DailyRollingFileSchedule { 
MONTHLY, 
WEEKLY, 
DAILY,
TWICE_DAILY, 
HOURLY, 
MINUTELY
};

(5)SocketAppender

log4cplus提供了SocketAppender,实现了C/S方式的日志记录,用于支持重定向到远程服务器。

①客户端程序需要做的工作

定义一个SocketAppender类型的挂接器

SharedAppenderPtr _append(new SocketAppender(host, 8888, "ServerName"));

把该挂接器加入到logger中

Logger::getRoot().addAppender(_append);

SocketAppender类型不需要Layout, 直接调用宏就可以将信息发往loggerServer了

LOG4CPLUS_INFO(Logger::getRoot(), "This is a test: ")

②服务器端程序需要做的工作

定义一个ServerSocket

ServerSocket serverSocket(port);

调用accept函数创建一个新的socket与客户端连接

Socket sock = serverSocket.accept();

此后即可用该sock进行数据read/write了:

     SocketBuffer msgSizeBuffer(sizeof(unsigned int));
     if(!clientsock.read(msgSizeBuffer)){
         return;
     }
     unsigned int msgSize = msgSizeBuffer.readInt();
     SocketBuffer buffer(msgSize);
     if(!clientsock.read(buffer)){
         return;
      }

为了将读到的数据正常显示出来,需要将SocketBuffer存放的内容转换成InternalLoggingEvent格式:

log4cplus::spi::InternalLoggingEvent event = readFromBuffer(buffer);

然后输出:

Logger logger = Logger::getInstance(event.getLoggerName()); logger.callAppenders(event);

注意:read/write是按照阻塞方式实现的,意味着对其调用直到满足了所接收或发送的个数才返回。

9.布局设置

log4cplus通过布局器(Layouts)来控制输出的格式,log4cplus提供了三种类型的Layouts,分别是SimpleLayout、PatternLayout、和TTCCLayout。

(1)SimpleLayout

一种简单格式的布局器,在输出的原始信息之前加上LogLevel和一个"-",如果初始化时没有将布局器附加到挂接器,则默认使用SimpleLayout。

(2)PatternLayout

一种有词法分析功能的模式布局器,类似于C语言的printf()函数,能够对预定义的转换标识符(conversion specifiers)进行解析,转换成特定格式输出。

以下代码片段演示了如何使用PatternLayout。

#include <log4cplus/log4cplus.h>

int main()
{
    //用Initializer类进行初始化
    log4cplus::Initializer initializer;

    //第1步:建立ConsoleAppender
    log4cplus::SharedAppenderPtr appender(new log4cplus::ConsoleAppender());

    //第2步:设置Appender的名称和输出格式(SimpleLayout)
    appender->setName(LOG4CPLUS_TEXT("console"));

    log4cplus::tstring pattern = LOG4CPLUS_TEXT("%D{%m/%d/%y %H:%M:%S,%Q} [%t] %-5p %c - %m [%l]%n");
    appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::PatternLayout(pattern)));

    //第3步:得到一个Logger实例,并设置其日志输出等级阈值
    log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));
    logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);

    //第4步:为Logger实例添加ConsoleAppender
    logger.addAppender(appender);

    //第5步:使用宏将日志输出
    LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));

    return 0;
}

PatterLayout支持的转换标识符主要包括:

  • "%%",转义为%, 即,std::string pattern = “%%” 时输出"%"。
  • "%c",输出logger名称,比如std::string pattern ="%c" 时输出: “test_logger.subtest”, 也可以控制logger名称的显示层次,比如"%c{1}“时输出"test_logger”,其中数字表示层次。
  • "%D",显示本地时间,当std::string pattern ="%D" 时输出:“2004-10-16 18:55:45”,%d显示标准时间,所以当std::string pattern ="%d" 时输出 “2004-10-16 10:55:45” (因为北京时间位于东8区,差8个小时)。
  • 可以通过%d{…}定义更详细的显示格式,比如%d{%H:%M:%s}表示要显示小时:分钟:秒。大括号中可显示的预定义标识符如下:
  • %a – 表示礼拜几,英文缩写形式,比如"Fri"
  • %A – 表示礼拜几,比如"Friday"
  • %b – 表示几月份,英文缩写形式,比如"Oct"
  • %B – 表示几月份,“October”
  • %c – 标准的日期+时间格式,如 “Sat Oct 16 18:56:19 2004”
  • %d – 表示今天是这个月的几号(1-31)“16”
  • %H – 表示当前时刻是几时(0-23),如 “18”
  • %I – 表示当前时刻是几时(1-12),如 “6”
  • %j – 表示今天是哪一天(1-366),如 “290”
  • %m – 表示本月是哪一月(1-12),如 “10”
  • %M – 表示当前时刻是哪一分钟(0-59),如 “59”
  • %p – 表示现在是上午还是下午, AM or PM
  • %q – 表示当前时刻中毫秒部分(0-999),如 “237”
  • %Q – 表示当前时刻中带小数的毫秒部分(0-999.999),如 “430.732”
  • %S – 表示当前时刻的多少秒(0-59),如 “32”
  • %U – 表示本周是今年的第几个礼拜,以周日为第一天开始计算(0-53),如 “41”
  • %w – 表示礼拜几,(0-6, 礼拜天为0),如 “6”
  • %W – 表示本周是今年的第几个礼拜,以周一为第一天开始计算(0-53),如 “41”
  • %x – 标准的日期格式,如 “10/16/04”
  • %X – 标准的时间格式,如 “19:02:34”
  • %y – 两位数的年份(0-99),如 “04”
  • %Y – 四位数的年份,如 “2004”
  • %Z – 时区名,比如 “GMT”
  • "%F",输出当前记录器所在的文件名称,比如std::string pattern ="%F" 时输出: “main.cpp”。
  • "%L",输出当前记录器所在的文件行号,比如std::string pattern ="%L" 时输出: “51”
  • "%l",输出当前记录器所在的文件名称和行号,比如std::string pattern ="%L" 时输出"main.cpp:51"。
  • "%m",输出原始信息,比如std::string pattern ="%m" 时输出: “teststr”,即上述代码中LOG4CPLUS_DEBUG的第二个参数,这种实现机制可以确保原始信息被嵌入到带格式的信息中。
  • "%n",换行符,没什么好解释的。
  • "%p",输出LogLevel,比如std::string pattern ="%p" 时输出: “DEBUG”。
  • "%t",输出记录器所在的线程ID,比如std::string pattern ="%t" 时输出: “1075298944”。
  • "%x",嵌套诊断上下文NDC (nested diagnostic context) 输出,从堆栈中弹出上下文信息,NDC可以用对不同源的log信息(同时地)交叉输出进行区分,关于NDC方面的详细介绍会在下文中提到。
  • 格式对齐,比如std::string pattern ="%-10m"时表示左对齐,宽度是10,此时会输出"teststr “,当然其它的控制字符也可以相同的方式来使用,比如”%-12d","%-5p"等等。

(3)TTCCLayout

TTCCLayout是在PatternLayout基础上发展的一种缺省的带格式输出的布局器, 其格式由时间,线程ID,Logger和NDC 组成(consists of time, thread, Logger and nested diagnostic context information, hence the name),因而得名。

10.基本步骤

使用log4cplus有六个基本步骤:

  1. 实例化一个封装了输出介质的appender对象;
  2. 实例化一个封装了输出格式的layout对象;
  3. 将layout对象绑定(attach)到appender对象;如省略此步骤,简单布局器SimpleLayout(参见5.1小节)对象会绑定到logger。
  4. 实例化一个封装了日志输出logger对象,并调用其静态函数getInstance()获得实例,log4cplus::Logger::getInstance(“logger_name”);
  5. 将appender对象绑定(attach)到logger对象;
  6. 设置logger的优先级,如省略此步骤,各种有限级的日志都将被输出。

代码示例:

#include <log4cplus/log4cplus.h>


int main()
{
    //用Initializer类进行初始化
    log4cplus::Initializer initializer;

    //第1步:创建ConsoleAppender(实例化一个appender对象)
    log4cplus::SharedAppenderPtr appender(new log4cplus::ConsoleAppender());

    //第2步:设置Appender的名称和输出格式(SimpleLayout)
    appender->setName(LOG4CPLUS_TEXT("console"));

    //第3步:实例化一个layout对象,将layout对象绑定到appender对象
    appender->setLayout(std::unique_ptr<log4cplus::Layout>(new log4cplus::SimpleLayout));

    //第4步:实例化一个封装了日志输出的Logger对象,并设置其日志输出等级阈值
    log4cplus::Logger logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("test"));

    //第5步:将appender对象绑定到logger对象
    logger.addAppender(appender);

    //第6步:设置日志log的优先级
    logger.setLogLevel(log4cplus::INFO_LOG_LEVEL);

    //使用宏将日志输出
    LOG4CPLUS_INFO(logger, LOG4CPLUS_TEXT("Hello world"));

    return 0;
}
11.注意事项

(1)如果使用ConsoleAppender()默认参数,那么控制台消息不会实时输出,需要等到缓冲区达到一定大小才会输出。当时这个可调试了好一会。因为我当时需要的效果就是实时输出到控制台与文件。代码如下:

log4cplus::SharedAppenderPtr append_console(new log4cplus::ConsoleAppender(false,true));

(2)输出数字、字符、字符串的方法如下:

    //第5步:使用宏将日志输出
    //数字输出
    for(int i=0; i<10; ++i)
    {
        LOG4CPLUS_INFO(logger, "Entering loop #" << i);
    }
    //字符输出
    char x='i';
    LOG4CPLUS_INFO(logger, "Entering loop #" << x);
    //字符串输出
    std::string y="xyz";
    LOG4CPLUS_INFO(logger, "Entering loop #" << LOG4CPLUS_C_STR_TO_TSTRING(y));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1415026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编

滴水逆向三期笔记与作业——02C语言——10 Switch语句反汇编 一、Switch语句1、switch语句 是if语句的简写2、break加与不加有什么特点?default语句可以省略吗&#xff1f;3、游戏中的switch语句&#xff08;示例&#xff09;4、添加case后面的值&#xff0c;一个一个增加&…

故障树分析蒙特卡洛仿真程序(附MATLAB完整代码)

故障树是一种特殊的倒立树状逻辑因果关系图&#xff0c;它用事件符号、逻辑门符号和转移符号描述系统中各种事件之间的因果关系&#xff0c;通过对引起系统故障的各种因素进行逻辑因果分析&#xff0c;确定导致故障发生的各种可能的原因&#xff0c;并通过定性和定量分析找出系…

如何限制 IP 多次重新访问

随着互联网的快速发展&#xff0c;网络安全问题日益突出。恶意 IP 多次重新访问是一种常见的手段&#xff0c;可能导致服务器负载过高、资源浪费、网站响应速度下降等问题。为了提高网络安全性&#xff0c;我们需要采取有效的措施来限制恶意 IP 的多次重新访问。下面简单的介绍…

Linux下安装openresty

Linux下安装openresty 十一、Linux下安装openresty11.1.概述11.2.下载OpenResty并安装相关依赖&#xff1a;11.3.使用wget下载:11.4.解压缩:11.5.进入OpenResty目录:11.6.编译和安装11.7.进入OpenResty的目录&#xff0c;找到nginx&#xff1a;11.8.在conf目录下的nginx.conf添…

C++笔记之作用域解析符::和命名空间、作用域的关系

C++笔记之作用域解析符::和命名空间、作用域的关系 —— 杭州 2024-01-26 code review 文章目录 C++笔记之作用域解析符::和命名空间、作用域的关系1.`命名空间`和`作用域`两个术语的联系和区别命名空间(Namespace)作用域(Scope)联系与区别2.`作用域解析符::`和`命名空间`…

分段函数线性化方法matlab测试

目录 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 4 matlab测试结果说明 5 分段线性化应用 1 使用0-1变量将分段函数转换为线性约束 2 连续函数采用分段线性化示例 3 matlab程序测试 clc;clear all; gn10;tn1; x_pfsdpvar(1, t…

桥接模式解析

桥接模式 意图 将抽象与其实现相分离&#xff0c;使得两者可以独立变化。 解释 案例&#xff1a;考虑武器有不同的特效&#xff0c;你想让不同的武器可以有不同的特效&#xff0c;你应该怎么做&#xff1f; 为每个武器创建不同的副本使得有不同的特效&#xff0c;还是你只单独…

记录一道ctf web题

0x00 前言 某同学发在群里一道不知道什么ctf的web题 0x01 bypass open_basedir 开始没想那么多&#xff0c;看到了可以执行phpinfo&#xff0c;直接先eval一个一句话上去看看什么情况&#xff1a; 接着发现了没有权限去读取/var/www/html以外的目录&#xff0c;那么我开始想的…

uniapp 使用echarts做折线图条形图。

提前10天把中烟活动做完了&#xff0c;以为能打酱油到除夕那天&#xff0c;结果又要做什么数据看板&#xff0c;方便烟草领导过年查看数据&#xff0c;还只给5天时间&#xff0c;真实压榨剥削啊&#xff0c;下辈子再也不‘拍黄片’了&#xff0c;不&#xff01;下份工作我就转前…

破解Windows系统密码(保姆级教学)

前言: 本篇博客只是技术分享并非非法传播知识,实验内容均是在虚拟机中进行,并非真实环境 正文: 看到题目大家都已经晓得这篇博客是干嘛了,我也不废话了,直接上win7素材 需要windows10破解过程的关注后在下面评论"已关注,请私聊"我会私发给你 一.windows7电脑密码破解…

JAVA_Set系列集合:HashSet、LinkedHashSet、TreeSet底层详解

先看看 Set 系列集合的位置&#xff1a; Set 系列集合的特点&#xff1a; 无序&#xff1a;存取顺序不一致 如存入张三、李四、王五。而遍历获取到的是李四, 张三, 王五 不重复&#xff1a;可以去除重复无索引&#xff1a;没有带索引的方法&#xff0c;所以不能使用普通for循…

MTE内存扩展精讲与实战

思考 1、常见的内存安全问题有哪些&#xff1f;举例说明&#xff1f; 2、内存安全的软件缓解技术有哪些&#xff1f;在optee上的应用&#xff1f; 3、MTE下的内存安全性如何保证&#xff1f;空间安全性&#xff1f;时间安全性&#xff1f; 4、MTE的架构细节&#xff1f;硬件原…

8.14划分字母区间(LC763-M)(附.length,.length(),.size()使用原理)

算法&#xff1a; 在遍历的过程中相当于是要找每一个字母的边界&#xff0c;如果找到之前遍历过的所有字母的最远边界&#xff0c;说明这个边界就是分割点了。 此时前面出现过所有字母&#xff0c;最远也就到这个边界了。 步骤&#xff1a; 统计每一个字符最后出现的位置从…

【代码随想录-数组】长度最小的子数组

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…

adb测试冷启动和热启动 Permission Denial解决

先清理日志 adb shell logcat -c 打开手机模拟器中的去哪儿网&#xff0c;然后日志找到包名和MainActivity adb shell logcat |grep Main com.Qunar/com.mqunar.atom.alexhome.ui.activity.MainActivity 把手机模拟器的去哪儿的进程给杀掉 执行 命令 adb shell am start -W…

2013年苏州大学837复试机试C/C++

2013年苏州大学复试机试 第一题 题目 假设有一堆数字&#xff08;小于100个&#xff09;需要对其做如下处理&#xff1a; 求平均数求标准差求方差 可用函数实现也可以不用 代码 #include <iostream> #include <sstream> //字符串流 #include <cmath> …

LabVIEW振动信号分析

LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换&#xff08;Hilbert-Huang Transform, HHT&#xff09;&#xff0c;并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具&#xff0c;特别适用于旋转机械等复杂系统的振动分析。开发了…

【linux】Debian防火墙

Debian系统默认没有安装防火墙&#xff0c;但用户可以根据需要自行选择并安装一个防火墙以增强系统安全性。 一、查看Debian 桌面系统的防火墙是否关闭 在Debian及其他基于Linux的桌面系统中&#xff0c;防火墙功能通常是由iptables或nftables规则集控制的&#xff0c;而ufw&…

《WebKit技术内幕》学习之十五(3): Web前端之未来

3 Web应用和Web运行环境 3.1 Web应用 HTML5提供了强大的能力&#xff0c;而不是支持Web网页这么简单。就目前而言&#xff0c;它已经初步提供了支持Web网页向Web应用方向发展的能力。相对于本地应用&#xff08;Native Application&#xff09;&#xff0c;Web前端领域也能够…

如何在yolov8中验证时计算FPS

ultralytics-main/ultralytics/engine/validator.py文件下&#xff0c;第200行左右&#xff0c;添加如下代码 LOGGER.info(fFPS:{(1000 / sum(self.speed.values())):.2f}) speed.values()是一个字典&#xff0c;包括preprocess,inference,loss,postprocess的时间&#xff0c;所…