c++ 日志框架G3log介绍及在嵌入式Linux上的移植(交叉编译)
在开发高性能的C++应用程序时,一个高效的日志框架是不可或缺的。G3log是一个开源的日志库,以其高性能和易于使用著称,特别适用于嵌入式Linux环境。本文将详细介绍G3log的主要特性和如何在嵌入式Linux平台上进行交叉编译。
G3log介绍
G3log 是一个开源、支持跨平台的异步 C++ 日志框架,支持自定义日志格式。基于 g2log 构建,提升了性能,支持自定义格式。它继承了g2log的优点,如轻量级、易用性及出色的性能表现,并在此基础上进行了大胆革新。
项目链接:https://github.com/KjellKod/g3log
G3log 主要特性
G3log 是一个基于g2log开发的开源异步C++日志框架,具备跨平台特性,允许用户根据需求定制日志格式。以下是G3log的主要特性:
- 日志和契约式设计框架:G3log提供了一套完整的日志系统和契约式编程支持,便于开发者编写可维护、可扩展的代码。
- 异步调用:相较于传统的同步日志记录方式,G3log采用异步机制,使得日志记录不会阻塞主线程,从而提升程序的响应速度。
- 线程安全:在多线程环境下,G3log通过巧妙的内部机制保证了线程安全,避免了数据竞争和死锁等问题。
- 队列式日志:G3log使用队列存储日志信息,确保日志记录过程的高效稳定。
- 捕获和记录SIGSEGV等信号:G3log能够捕获并记录严重的运行时信号,如SIGSEGV,并在Linux/OSX上生成堆栈跟踪信息,方便开发者进行调试。
- 跨平台支持:G3log支持Windows, Linux 和 OSX三个操作系统,能够满足不同开发环境的需求。
- 多种编译器支持:G3log可以使用Visual Studio 2013, Clang 和 GCC4.7 进行构建,便于不同环境下的开发工作。
性能对比
G3log与log4cplus进行了在Linux和Windows环境下的日志记录性能对比测试。结果显示,在这两种操作系统中,G3log明显表现出了更快的日志记录速度。这得益于G3log的异步处理机制和高效的内部实现。
简单地对log4cplus和g3log的性能做了测试,打印1百万条日志信息所需时间如下:
框架 | 模式 | Linux | Windows |
---|---|---|---|
log4cplus | 同步 | 4s | 6s |
log4cplus | 异步 | 1.9s | 64s |
G3log | 异步 | 2.3s | 待做 |
从表中可以看出,在Linux环境下,G3log的异步日志记录性能优于log4cplus的异步模式;而Windows环境下的同步日志记录性能,G3log也优于log4cplus。
虽然还有个spdlog号称全球最快,但是g3log作者对spdlog的对比,仅供参考:
https://kjellkod.wordpress.com/2015/06/30/the-worlds-fastest-logger-vs-g3log/
https://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++
g3log的测试程序如下:
#include <string>
#include <iostream>
#include <memory>
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>std::string path_to_log_file = "./";
std::string log_file = "g3logfile";std::unique_ptr<g3::LogWorker> worker;void log_init()
{worker = g3::LogWorker::createLogWorker();auto handle = worker->addDefaultLogger(log_file, path_to_log_file);g3::initializeLogging(worker.get());
}void log_shutdown()
{g3::internal::shutDownLogging();
}int main(int argc, char* argv[])
{log_init();for (int i = 0; i < 1000000; i++){// use LOGF which like printfLOGF(INFO, "logging test %d", i);}log_shutdown();return 0;
}
编译测试:
g++ -std=c++14 -Wall -O3 -I/home/yang/usr/lib/g3log/include -L/home/yang/usr/lib/g3log/lib -lg3logger main.cc -o main
G3log在多线程编程中的应用
线程安全的保证
在线程编程中,线程安全是至关重要的。G3log在设计之初便将线程安全作为核心考量之一,采用高效的锁机制来隔离可能引起冲突的操作。即使在高并发环境下,G3log也能确保日志记录过程的稳定与可靠。这种设计极大地简化了多线程编程中的复杂度,为软件的整体质量提供了坚实的保障。
异步调用在多线程中的实践
异步调用是G3log的一大亮点。在传统同步模式下,每当应用程序需要记录一条日志时,主线程必须暂停当前任务,等待日志写入完成后才能继续执行。这种方式虽然简单直接,但在处理大量并发请求时却显得力不从心。G3log通过引入异步机制,使得日志记录变成了一项非阻塞性的工作。具体来说,当某个线程产生日志信息时,它只需将这些信息暂时存放在一个缓冲区中,而无需等待实际写入磁盘的过程完成。与此同时,G3log会在后台独立运行一个或多个线程,专门负责将缓冲区中的数据持久化到文件系统中。这样一来,不仅极大地提升了程序的响应速度,还有效避免了因日志操作导致的性能瓶颈问题。
代码示例:多线程环境下的G3log使用
为了更直观地展示G3log在多线程环境中的应用效果,下面将通过一个简单的示例来进行说明。假设你正在开发一个需要处理大量并发请求的服务器端应用,并希望利用G3log来记录各个线程的活动情况。
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>
#include <thread>
#include <vector>void threadFunction(int id) {// 每个线程记录一条日志LOG(INFO) << "Thread " << id << " is running.";
}int main() {// 初始化日志系统g3::initialize_logging(g3::logworker::initLogWorker());std::vector<std::thread> threads;for (int i = 0; i < 10; ++i) {threads.emplace_back(threadFunction, i);}// 等待所有线程结束for (auto& t : threads) {t.join();}// 清理日志系统g3::shutdown_logging();return 0;
}
在这个例子中,我们创建了一个包含10个线程的集合,并为每个线程分配了一个独立的任务——记录一条包含线程编号的日志信息。通过观察最终生成的日志文件,我们可以清楚地看到所有线程的执行顺序及状态变化,这对于调试多线程程序来说是非常有帮助的。此外,由于G3log具备优秀的异步处理能力,上述代码在实际运行时并不会出现明显的延迟现象,充分体现了其在高并发场景下的优越性能。
在嵌入式Linux上的移植
准备交叉编译工具链
首先,我们需要准备交叉编译工具链。这里以ARM和RISC-V架构为例,创建一个toolchain.cmake
文件:
# 交叉编译工具链配置文件
# 用于嵌入式Linux系统和RISC-V MCU的交叉编译# 设置系统名称
set(CMAKE_SYSTEM_NAME Linux)# 设置处理器架构变量,可以通过命令行参数传入
# 例如: cmake -DTARGET_ARCH=arm ..
if(NOT DEFINED TARGET_ARCH)set(TARGET_ARCH "arm" CACHE STRING "Target architecture (arm or riscv)")
endif()# 设置ARM工具链路径
set(ARM_TOOLCHAIN_PATH "/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi")
# 设置RISC-V工具链路径
set(RISCV_TOOLCHAIN_PATH "/opt/tronlong/tina5.0_v1.0/rtos/lichee/rtos/tools/riscv64-elf-x86_64-20201104")# 根据目标架构设置主工具链
if(${TARGET_ARCH} STREQUAL "arm")# ARM Linux工具链配置set(CMAKE_C_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-gcc)set(CMAKE_CXX_COMPILER ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-g++)set(CMAKE_FIND_ROOT_PATH /opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/)set(CMAKE_SYSTEM_PROCESSOR arm)# 设置额外的编译标志set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfloat-abi=hard -mfpu=neon" CACHE STRING "" FORCE)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mfloat-abi=hard -mfpu=neon" CACHE STRING "" FORCE)# 设置链接器set(CMAKE_LINKER ${CMAKE_C_COMPILER})set(CMAKE_AR ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-ar)set(CMAKE_RANLIB ${ARM_TOOLCHAIN_PATH}/arm-poky-linux-gnueabi-ranlib)elseif(${TARGET_ARCH} STREQUAL "riscv")# RISC-V工具链配置 (C906核心)set(CMAKE_C_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-gcc)set(CMAKE_CXX_COMPILER ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-g++)set(CMAKE_FIND_ROOT_PATH ${RISCV_TOOLCHAIN_PATH}/riscv64-unknown-elf)set(CMAKE_SYSTEM_PROCESSOR riscv)# 设置RISC-V特定的编译标志 (C906核心)set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=rv64gcv0p7 -mabi=lp64d" CACHE STRING "" FORCE)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=rv64gcv0p7 -mabi=lp64d" CACHE STRING "" FORCE)# 设置链接器set(CMAKE_LINKER ${CMAKE_C_COMPILER})set(CMAKE_AR ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ar)set(CMAKE_RANLIB ${RISCV_TOOLCHAIN_PATH}/bin/riscv64-unknown-elf-ranlib)else()message(FATAL_ERROR "不支持的目标架构: ${TARGET_ARCH}. 请使用 'arm' 或 'riscv'")
endif()# 设置查找规则
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)# 禁用系统库路径
set(CMAKE_SKIP_RPATH TRUE)# 设置交叉编译环境的库和头文件搜索路径
set(CMAKE_SYSROOT ${CMAKE_FIND_ROOT_PATH}) # 关键!!!,不能漏掉这个设置
set(CMAKE_FIND_ROOT_PATH /root/arm_install)
交叉编译G3log
接下来,从GitHub下载G3log的源码。注意,由于我的GCC版本为5.3,不支持C++17,因此需要下载1.3.4版本的G3log。
下载源码后,在根目录下创建一个build
目录,进入build
目录并执行以下指令:
cmake ../ \-DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake \-DTARGET_ARCH=arm \-DADD_G3LOG_UNIT_TEST=OFF \-DG3_SHARED_LIB=ON \-DUSE_DYNAMIC_LOGGING_LEVELS=OFF \-DENABLE_FATAL_SIGNALHANDLING=ON \-DCMAKE_INSTALL_PREFIX=${HOME}/arm_install
执行完上述指令后,分别运行make
和make install
命令,即可完成G3log在ARM架构下的交叉编译和安装。
G3log使用举例
以下是G3log的基本使用示例:
#include <iostream>
#include <g3log/g3log.hpp>
#include <g3log/logworker.hpp>using namespace std;string path_to_log_file = "/tmp/";
string log_file = "g3log_file";std::unique_ptr<g3::LogWorker> worker;void log_init()
{worker = g3::LogWorker::createLogWorker();auto handle = worker->addDefaultLogger(log_file, path_to_log_file);g3::initializeLogging(worker.get());
}void log_shutdown()
{g3::internal::shutDownLogging();
}int main(int argc, char* argv[])
{log_init();// use LOGF which like printfLOGF(INFO, "Hi log %d", 123);LOGF(WARNING, "Printf-style syntax is also %s", "available”);// use LOG wich like std::coutLOG(INFO) << "Hi " << "LOG";log_shutdown();return 0;
}
CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 3.5)
project(g3log_example)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 获取 g3log 库
find_package(g3log REQUIRED)# 添加你的可执行文件
add_executable(g3log_example main.cpp)# 链接 g3log 库
target_link_libraries(g3log_example g3log)
cmake .. -DCMAKE_TOOLCHAIN_FILE=../toolchain1.cmake -DTARGET_ARCH=arm
在这个简单的示例中,我们首先初始化了日志系统,并指定了日志文件的存储目录。之后,通过LOG
宏记录了不同级别的日志信息,包括INFO、WARNING、DEBUG和ERROR。
总结
通过对G3log的深入探讨,我们不仅领略了这款日志框架在异步调用、跨平台支持以及线程安全等方面展现出的强大功能,还通过一系列实用的代码示例,直观地感受到了其在实际开发中的便捷与高效。G3log凭借其卓越的性能表现和灵活的配置选项,为C++开发者提供了一个理想的日志解决方案。无论你是初学者还是经验丰富的专业人士,都能够从中受益匪浅。未来,随着技术的不断进步与应用场景的日益丰富,相信G3log将继续发挥重要作用,助力更多项目实现高效、稳定的目标。
其他资源
https://www.open-open.com/lib/view/open1408677978459.html
https://www.showapi.com/news/article/66ec3f9f4ddd79f11a0fe3fb
https://blog.csdn.net/wqfhenanxc/article/details/88892996
相关文章:
c++ 日志框架G3log介绍及在嵌入式Linux上的移植(交叉编译)
在开发高性能的C应用程序时,一个高效的日志框架是不可或缺的。G3log是一个开源的日志库,以其高性能和易于使用著称,特别适用于嵌入式Linux环境。本文将详细介绍G3log的主要特性和如何在嵌入式Linux平台上进行交叉编译。 G3log介绍 G3log 是一…...
Buffer overFolw---Kryo序列化出现缓冲区溢出的问题解决
问题: 由于我的数据量太大,我设置批次为10000万,50w数据大概有400M左右,然后进行spark数据处理时候报错为org.apache.spark.SparkException:Kryo serialization failed:Buffer overFolw.Available:0,rquired 58900977,To …...
leetcode日常刷题
题目:K个一组翻转链表 思路 题目要求k个一组进行反转,首先考虑到如果k为1,那就可以直接返回链表头,这种情况没必要翻转。 如果只有一个节点或者head为空结点,直接返回head即可(一个节点翻转k次都是本身&am…...
菜鸡前端计算机强基计划之CS50 第七课 python 入门—— Python 中yield专题学习
菜鸡前端计算机强基计划之CS50 第七课 python 入门—— Python 中yield专题学习 1. 什么是 yield?直观感受 2. 生成器是什么?一个简单的例子 3. yield 的工作原理(图形化解释)4. yield 和内存的魔法用列表返回所有值用生成器逐步生…...
密码学——知识问答
目录 1、阐述公开密钥算法的定义,结合RSA算法说明公钥密码的基本要求。 说明公钥与私钥两种密码学并举例与其应用 1. 公钥密码学(非对称加密): 2. 私钥密码学(对称加密): 对比公钥与私钥密码…...
Talos-docker版本中创建 Kubernetes 集群
在talos容器化版本中部署Kubernetes集群,用于折腾学习。 1.系统信息 虚拟机软件:VMware Worktation 虚拟机配置:4G内存 4vCPU 200GB磁盘 操作系统:CentOS7.9 docker:20.10.15 PS:为啥VMware Worktat…...
【Excel使用技巧】某列保留固定字段或内容
目录 ✅ 方法一:使用 Excel 公式提取 body 部分 🔍 解释: ✅ 方法二:批量处理整列数据 🚨 注意事项 🚨 处理效果 我想保留Excel某一列的固定内容,比如原内容是: thread entry i…...
matlab 模拟 闪烁体探测器全能峰
clc;clear;close all %% 参数设置 num_events 1e5; % 模拟事件数 E 662e3; % γ射线能量(eV) Y 38000; % 光产额(photon/MeV,NaI(Tl)) eta 0.2; % 量子效率 G 1e6; …...
【leetcode hot 100 74】搜索二维矩阵
解法一:双重二分查找 class Solution {public boolean searchMatrix(int[][] matrix, int target) {int nmatrix.length, mmatrix[0].length;int row10, row2n-1, col10, col2m-1;int row_mid, col_mid;while(row1<row2){row_mid (row1row2)/2;while(col1<c…...
Maven 中 maven.test.skip 与skipTests 区别
在 Maven 中,maven.test.skip 和 skipTests 都用于控制测试的跳过行为,但它们的作用范围和底层机制有显著区别。以下是详细对比: 1. maven.test.skip 定义 maven.test.skip 是一个用户自定义属性(需在 pom.xml 的 <propertie…...
LLM - R1 强化学习 DRPO 策略优化 DAPO 与 Dr. GRPO 算法 教程
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/146533892 在强化学习算法中,DAPO (Decoupled Clip and Dynamic Sampling Policy Optimization),通过解耦裁剪和动态采样策…...
element-plus中,Loading 加载组件的使用
一.基本使用 给一个组件,如:table表格,加上v-loading"true"即可。 举例:复制如下代码。 <template><el-table v-loading"loading" :data"tableData" style"width: 100%"><…...
部署完dify:localhost/install 页面不停转圈圈,报错CROS error
解决办法 docker/.env 文件中,需要配置如下: NGINX_HTTPS_ENABLEDtrue NGINX_ENABLE_CERTBOT_CHALLENGEtrue 把Nginx的跨域请求打开...
UE4学习笔记 FPS游戏制作17 让机器人持枪 销毁机器人时也销毁机器人的枪 让机器人射击
添加武器插槽 打开机器人的Idle动画,方便查看武器位置 在动画面板里打开骨骼树,找到右手的武器节点,右键添加一个插槽,重命名为RightWeapon,右键插槽,添加一个预览资产,选择Rifle,根…...
【网络丢包】原因排查及优化
在流式响应中,丢包现象可能由多种因素引起,详细的原因分析、排查方法及优化策略: 一、丢包原因分析 网络拥塞 当网络带宽不足或流量突增时,路由器/交换机可能丢弃超出处理能力的数据包。 硬件问题 网卡、路由器、交换机等设备故…...
Spring Boot 实战:MD5 密码加密应用全解析
Spring Boot 实战:MD5 密码加密应用全解析 1. 引言 在应用开发中,密码安全是用户隐私保护的核心环节。直接存储明文密码存在极大的安全风险(如数据库泄露导致用户信息被盗)。MD5 加密作为一种广泛使用的哈希算法,可将…...
Android 底部EditView输入时悬浮到软键盘上方
1. 修改 Activity 的 Manifest 配置 确保你的 Activity 在 AndroidManifest.xml 中有以下配置: <activityandroid:name".YourActivity"android:windowSoftInputMode"adjustResize|stateHidden" /> 关键点: adjustResize 是…...
【deepseek 学c++】weakptr引用场景
std::weak_ptr 是 C 中与 std::shared_ptr 配合使用的智能指针,它本身不拥有资源的所有权,仅观察资源的状态,主要用于解决 shared_ptr 的循环引用问题和临时访问共享资源的需求。以下是 weak_ptr 的典型应用场景和核心价值:![ 为…...
从技术架构和生态考虑,不是单纯的配置优化,还有哪些方式可以提高spark的计算性能
从技术架构和生态系统层面提升Spark的计算性能,可采取以下核心策略: 一、计算模型重构与执行引擎升级 1. 弹性分布式数据集(RDD)的血统优化 通过RDD的Lineage(血统)机制实现容错时,采用增量式…...
怎样进行服务器的日常安全监控和审计?
服务器的日常安全监控和审计是保障服务器安全运行的重要措施,以下是一些常见的方法和工具: 系统日志监控 启用日志功能:确保服务器操作系统、应用程序和数据库等都启用了详细的日志记录功能。例如,Linux 系统中的 syslog&#x…...
Java 集合框架面经
1、说说有哪些常见的集合框架? 集合框架可以分为两条大的支线: Map 接口:表示键值对的集合,一个键映射到一个值。键不能重复,每个键只能对应一个值。Map 接口的实现类包括 HashMap、LinkedHashMap、TreeMap 等。Colle…...
【已解决】Git:为什么 .gitignore 不生效?如何停止跟踪已提交文件并阻止推送?
你可能遇到的问题 你已经提交了某个文件夹(如 dataset)到 Git 仓库,之后修改了它,但发现修改内容被 Git 持续跟踪,无法通过 .gitignore 忽略。尝试在 .gitignore 中添加规则后,修改的文件仍然显示为"…...
MOSN(Modular Open Smart Network)-04-TLS 安全链路
前言 大家好,我是老马。 sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFAStack-00-sofa 技术栈概览 MOSN(Modular O…...
SICAR 标准 KUKA 机器人标准功能块说明手册
功能块名称:LSicar_Robot_KUKA_PrD 目录 1. 概述 2. 功能说明 2.1 程序控制 2.2 状态监控 2.3 报警与故障处理 2.4 驱动控制 3. 关键参数说明 4. 操作步骤指南 4.1 初始化配置 4.2 运行控制 4.3 状态监控 5. 常见故障处理 6. 注意事项 附录1:程序段索引 附录…...
QT三 自定义控件,自定义控件的事件处理自定义事件过滤,原始事件过滤
一 自定义控件 现在的需求是这样: 假设我们要在QWidget 上做定制,这个定制包括了关于 一些事件处理,意味着要重写QWidget的一些代码,这是不实际的,因此我们需要自己写一个MyWidget继承QWidget,然后再MyWi…...
Leetcode算法方法总结
1. 双指针法解决链表/数组题目 只要数组有序,就要想到双指针做法。还有二分法 回文串一般也会用到双指针,回文串的长度由于可能是奇数也可能是偶数,所以在寻找时,既需要寻找奇数长度的回文串,也需要寻找偶数长度的回文…...
【Elasticsearch基础】基本核心概念介绍
Elasticsearch作为当前最流行的分布式搜索和分析引擎,其强大的功能背后是一套精心设计的核心概念体系。本文将深入解析Elasticsearch的五大核心概念,帮助开发者构建坚实的技术基础,并为高效使用ES提供理论支撑。 1 索引(Index&…...
docker远程debug
1. 修改 Java 启动命令 在 Docker 容器中启动 Java 程序时,需要添加 JVM 调试参数,jdk8以上版本 java -agentlib:jdwptransportdt_socket,servery,suspendn,address*:5005 -jar your-app.jar jdk8及以下版本: java -Xdebug -Xrunjdwp:tra…...
华为eNSP-配置静态路由与静态路由备份
一、静态路由介绍 静态路由是指用户或网络管理员手工配置的路由信息。当网络拓扑结构或者链路状态发生改变时,需要网络管理人员手工修改静态路由信息。相比于动态路由协议,静态路由无需频繁地交换各自的路由表,配置简单,比较适合…...
CentOS 7下安装PostgreSQL 15
一、简介 PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为基础的对象关系型数据库管理系统。POSTGRES的许多领先概念只是在比较迟的时候才出现在商业…...
时序数据库 InfluxDB(一)
时序数据库 InfluxDB(一) 数据库种类有很多,比如传统的关系型数据库 RDBMS( 如 MySQL ),NoSQL 数据库( 如 MongoDB ),Key-Value 类型( 如 redis )…...
动态添加view方法-微信小程序
在微信小程序中,通过动态数据绑定和条件渲染来实现动态添加 view 组件的效果。 以下是一个简单的示例,展示如何根据数据动态添加 view。 WXML 文件 在 WXML 文件中,使用 wx:for 指令来遍历数组,并动态生成 view 组件。 <view…...
Java中清空集合列表元素有哪些方式
在 Java 里,存在多种清空列表的方式,下面为你汇总并附上对应的示例代码: import java.util.ArrayList; import java.util.List;public class ListClearDemo {public static void main(String[] args) {// 初始化一个列表List<String> …...
QOpenGLWidget动态加载功能实现教程(Qt+OpenGL)
QOpenGLWidget动态加载功能实现教程 我需要在Qt里面使用QOpenGLWidget显示OpenGL窗口,并且需要实现加载模型后重新渲染更新窗口的功能,但是一直无法更新被卡住了,现在把问题解决了总结一下整个实现过程。 创建一个自己的OpenGLWidget类 QOp…...
00.【Linux系统编程】 Linux初识(云服务器设置CentOS并使用、Xshell链接云服务器)
目录 一、华为云服务器免费体验申请 二、Xshell远程链接创建好的华为云服务器 2.1 下载Xshell 2.2 Xshell远程连接华为云服务器 一、华为云服务器免费体验申请 华为云官网 1. 进入华为云官网,最上面一栏点活动,并进入免费体验中心。 2. 找到含有“…...
数据结构-二叉链表存储的二叉树
树形结构是一类重要的非线性数据结构,其中以树和二叉树最为常用。对于每一个结点至多只有两课子树的一类树,称其为二叉树。二叉树的链式存储结构是一类重要的数据结构,其形式定义如下: 而二叉树的前序、中序遍历是非常重要的能够访…...
鸿蒙Flutter实战:20. Flutter集成高德地图,同层渲染
本文以同层渲染为例,介绍如何集成高德地图 完整代码见 Flutter 鸿蒙版 Demo 概述 Dart 侧 核心代码如下,通过 OhosView 来承载原生视图 OhosView(viewType: com.shaohushuo.app/customView,onPlatformViewCreated: _onPlatformViewCreated,creation…...
idea中快速注释函数
在IntelliJ IDEA中,有多种方法可以快速注释函数。 使用快捷键 你可以使用以下快捷键来快速注释函数[3]: 行注释:使用Ctrl/(Windows系统)或Command/(Mac系统)可以在当前行前添加或删除单行注释…...
Leetcode13-罗马数字转整数
题目链接:13. 罗马数字转整数 - 力扣(LeetCode) 如同上一题,直接用暴力法破解,简单好理解 int romanToInt(char* s) {int len strlen(s);int res 0;for(int i 0; i < len; i) {switch(s[i]) {case M:res 1000…...
3、pytest实现参数化
在 pytest 中,参数化(parametrization)是一种强大的功能,可以让你用不同的输入数据重复执行同一个测试函数。这种功能非常有用,可以帮助你显著减少重复代码并提高测试覆盖率。 参数化的主要作用是: 测试多…...
深入理解指针(4)(C语言版)
文章目录 前言一、回调函数是什么(一)定义(二)工作原理(三)应用场景 二、qsort举例(一)qsort函数简介(二)比较函数的定义(三)使用示例…...
【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的日志管理:Logback 的集成
<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整…...
记录一次渗透测试/常用命令
渗透测试常用命令速览:从扫描到提权再到流量劫持 在渗透测试中,命令行工具是我们的得力助手。本文总结了我最近在测试虚拟机靶机(IP: 192.168.73.129)时用到的主要命令,涵盖网络扫描、暴力破解、权限提升、数据修改和…...
C++11QT复习(二)
文章目录 Day4-4 New 与 delete 表达式(2025.03.20)1. new 表达式的三个步骤2. delete 表达式的两个步骤3. new[] 与 delete[] Day5 类的定义和关键字再探(2025.03.24)1. C 关键字 const、static、extern2. 类的定义:C…...
Pytorch学习笔记(十)Learning PyTorch - Learning PyTorch with Examples
这篇博客瞄准的是 pytorch 官方教程中 Learning PyTorch 章节的 Learning PyTorch with Examples 部分。 官网链接:https://pytorch.org/tutorials/beginner/pytorch_with_examples.html 完整网盘链接: https://pan.baidu.com/s/1L9PVZ-KRDGVER-AJnXOvlQ?pwdaa2m…...
如何使用DeepSeek编写测试用例?
一、DeepSeek在测试用例设计中的定位 DeepSeek作为AI工具,并非直接替代测试设计,而是通过以下方式提升效率: 快速生成基础用例框架(等价类、边界值等) 智能补充易遗漏场景(如特殊字符、异常流) 自动化脚本片段生成(Python/pytest/JUnit等) 测试数据构造建议(符合业务…...
sql server如何提高索引命中率
#新星杯14天创作挑战营第9期# 前言 近期发现以前开发的系统运行缓慢,经排查,发现有很大的优化空间。数据库版本使用的是sql server,主要有以下一些问题点:数据表无索引、一些不规范的写法(例如in、大表关联࿰…...
FALL靶机
下载靶机,可以看到靶机地址 在kali上扫描靶机的端口和目录文件 访问:http://192.168.247.146/test.php,他提示我们参数缺失 我们爆破一下他的参数 使用kali自带的fuzz FUZZ就是插入参数的位置 -w 指定字典文件 wfuzz -u "http://192.…...
北斗导航 | 改进最小二乘残差法的接收机自主完好性监测算法原理,公式,应用,研究综述,matlab代码
改进最小二乘残差法的接收机自主完好性监测算法研究 摘要 本文针对传统最小二乘残差RAIM算法在复杂环境下检测性能不足的问题,提出了一种基于加权抗差估计的改进算法。通过引入IGGⅢ权函数构建抗差最小二乘模型,结合滑动窗口方差估计和自适应阈值调整机制,显著提升了算法对…...
WPF 浅述ToolTipService.ShowOnDisabled
WPF 浅述ToolTipService.ShowOnDisabled ToolTipService.ShowOnDisabled 属性可以让工具提示在控件禁用状态下仍然显示。这是一个非常方便且简洁的方式。 使用 ToolTipService.ShowOnDisabled,你可以通过设置 ToolTipService.ShowOnDisabled 属性来确保即使在控件禁…...