添加cpp和Linux相关记录

This commit is contained in:
taynpg 2024-03-08 14:01:18 +08:00
parent 3de0fd9fcb
commit 276e3411c6
23 changed files with 2039 additions and 22 deletions

44
cpp/C++_MJ.txt Normal file
View File

@ -0,0 +1,44 @@
1.sizeof 不是函数,是运算符。
2.c++没有写构造函数,C++编译器不一定自动写一个默认构造函数。
3.c++会对函数名符号进行改编,可以支持函数重载(name mangling)。
4.被extern "C" { 修饰的代码会按照C语言的规则编译、声明被exeter "C"包含,CPP实现可以不要。
5.函数调用要开辟会回收栈空间。
6.incline 建议编译器 incline。
[什么时候使用inline?]
(1)函数体积不大
(2)频繁调用
7.汇编
从上往下是向下兼容,实际比如影响AX也是会影响x64中的RAX
x64
RAX\RBX\RCX\RDX : 通用寄存器
x86
EAX\EBX\ECX\EDX : 通用寄存器
16位
AX\BX\CX\DX : 通用寄存器
8位
AH H High
AL L Low
8.C++中使用内联汇编
汇编中没有;
__asm {
}
word 2字节.
move dest, src
[地址值]([]里面一定是地址值)
call 调用
字节占用都是低位=>高位占用,
已经占用的内存,内部采集大小端方式:
int a = 3;
(高 ----> 低)
00000000 00000000 00000000 00000011
[大小端] 一般来讲,大多数都是小端模式(低字节放低地址)。
lea dest, [地址值] (复制地址值)(load effect address)
mov dest, [地址值] (复制地址值内容)
xor a, b (a,b的异或结果复制给a)
add 加, sub 减, inc 自增, dec 自减, jmp 跳转
xor 异或

52
cpp/clangd.txt Normal file
View File

@ -0,0 +1,52 @@
"C_Cpp.intelliSenseEngine": "Disabled", // 禁用微软 Cpptools 插件的提示功能
"C_Cpp.codeAnalysis.runAutomatically": false,
"C_Cpp.formatting": "Disabled",
// clangd
"clangd.path": "c:\\Users\\Sirius\\AppData\\Roaming\\Code\\User\\globalStorage\\llvm-vs-code-extensions.vscode-clangd\\install\\15.0.3\\clangd_15.0.3\\bin\\clangd.exe", // clangd 安装路径
// Clangd 运行参数(在终端/命令行输入 clangd --help-list-hidden 可查看更多)
"clangd.arguments": [
"--all-scopes-completion", // 全局补全(补全建议会给出在当前作用域不可见的索引,插入后自动补充作用域标识符),例如在main()中直接写cout,即使没有`#include <iostream>`,也会给出`std::cout`的建议,配合"--header-insertion=iwyu",还可自动插入缺失的头文件
"--background-index", // 后台分析并保存索引文件
"--clang-tidy", // 启用 Clang-Tidy 以提供「静态检查」,下面设置 clang tidy 规则
"--clang-tidy-checks=performance-*, bugprone-*, misc-*, google-*, modernize-*, readability-*, portability-*",
"--compile-commands-dir=${workspaceFolder}/.vscode", // 编译数据库(例如 compile_commands.json 文件)的目录位置
"--completion-parse=auto", // 当 clangd 准备就绪时,用它来分析建议
"--completion-style=detailed", // 建议风格:打包(重载函数只会给出一个建议);还可以设置为 detailed
// "--query-driver=/usr/bin/clang++", // MacOS 上需要设定 clang 编译器的路径,homebrew 安装的clang 是 /usr/local/opt/llvm/bin/clang++
// 启用配置文件(YAML格式)项目配置文件是在项目文件夹里的“.clangd”,用户配置文件是“clangd/config.yaml”,该文件来自:Windows: %USERPROFILE%\AppData\Local || MacOS: ~/Library/Preferences/ || Others: $XDG_CONFIG_HOME, usually ~/.config
"--enable-config",
"--fallback-style=Webkit", // 默认格式化风格: 在没找到 .clang-format 文件时采用,可用的有 LLVM, Google, Chromium, Mozilla, Webkit, Microsoft, GNU
"--function-arg-placeholders=true", // 补全函数时,将会给参数提供占位符,键入后按 Tab 可以切换到下一占位符,乃至函数末
"--header-insertion-decorators", // 输入建议中,已包含头文件的项与还未包含头文件的项会以圆点加以区分
"--header-insertion=iwyu", // 插入建议时自动引入头文件 iwyu
"--include-cleaner-stdlib", // 为标准库头文件启用清理功能(不成熟!!!)
"--log=verbose", // 让 Clangd 生成更详细的日志
"--pch-storage=memory", // pch 优化的位置(Memory 或 Disk,前者会增加内存开销,但会提升性能)
"--pretty", // 输出的 JSON 文件更美观
"--ranking-model=decision_forest", // 建议的排序方案:hueristics (启发式), decision_forest (决策树)
"-j=12" // 同时开启的任务数量
],
// Clangd 找不到编译数据库(例如 compile_flags.json 文件)时采用的设置,缺陷是不能直接索引同一项目的不同文件,只能分析系统头文件、当前文件和include的文件
"clangd.fallbackFlags": [
"-pedantic",
"-Wall",
"-Wextra",
"-Wcast-align",
"-Wdouble-promotion",
"-Wformat=2",
"-Wimplicit-fallthrough",
"-Wmisleading-indentation",
"-Wnon-virtual-dtor",
"-Wnull-dereference",
"-Wold-style-cast",
"-Woverloaded-virtual",
"-Wpedantic",
"-Wshadow",
"-Wunused",
"-pthread",
"-fuse-ld=lld",
"-fsanitize=address",
"-fsanitize=undefined",
"-stdlib=libc++",
"-std=c++20"
],

285
cpp/cmake.txt Normal file
View File

@ -0,0 +1,285 @@
下面先介绍一些CMake项目通常都需要进行的配置。下面介绍的内容以make作为构建工具作为示例。
下面的示例代码可以在开源项目cmake-template(发布在Gitee平台)中查看(当前commit id:c7c6b15)。把仓库克隆下来结合源码阅读本文效果更佳,如果有帮助,请点下Star哟。
1 设置项目版本和生成version.h
一般来说,项目一般需要设置一个版本号,方便进行版本的发布,也可以根据版本对问题或者特性进行追溯和记录。
通过project命令配置项目信息,如下:
project(CMakeTemplate VERSION 1.0.0 LANGUAGES C CXX)
第一个字段是项目名称;通过VERSION指定版本号,格式为main.minor.patch.tweak,并且CMake会将对应的值分别赋值给以下变量(如果没有设置,则为空字符串):
PROJECT_VERSION, <PROJECT-NAME>_VERSION
PROJECT_VERSION_MAJOR, <PROJECT-NAME>_VERSION_MAJOR
PROJECT_VERSION_MINOR, <PROJECT-NAME>_VERSION_MINOR
PROJECT_VERSION_PATCH, <PROJECT-NAME>_VERSION_PATCH
PROJECT_VERSION_TWEAK, <PROJECT-NAME>_VERSION_TWEAK
因此,结合前一篇文章提到的configure_file命令,可以配置自动生成版本头文件,将头文件版本号定义成对应的宏,或者定义成接口,方便在代码运行的时候了解当前的版本号。
比如:
configure_file(src/c/cmake_template_version.h.in "${PROJECT_SOURCE_DIR}/src/c/cmake_template_version.h")
假如cmake_template_version.h.in内容如下:
#define CMAKE_TEMPLATE_VERSION_MAJOR @CMakeTemplate_VERSION_MAJOR@
#define CMAKE_TEMPLATE_VERSION_MINOR @CMakeTemplate_VERSION_MINOR@
#define CMAKE_TEMPLATE_VERSION_PATCH @CMakeTemplate_VERSION_PATCH@
执行cmake配置构建系统后,将会自动生成文件:cmake_template_version.h,其中@<var-name>@将会被替换为对应的值:
#define CMAKE_TEMPLATE_VERSION_MAJOR 1
#define CMAKE_TEMPLATE_VERSION_MINOR 0
#define CMAKE_TEMPLATE_VERSION_PATCH 0
2 指定编程语言版本
为了在不同机器上编译更加统一,最好指定语言的版本,比如声明C使用c99标准,C++使用c++11标准:
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
这里设置的变量都是CMAKE_开头(包括project命令自动设置的变量),这类变量都是CMake的内置变量,正是通过修改这些变量的值来配置CMake构建的行为。
CMAKE_、_CMAKE或者以下划线开头后面加上任意CMake命令的变量名都是CMake保留的。
3 配置编译选项
通过命令add_compile_options命令可以为所有编译器配置编译选项(同时对多个编译器生效);通过设置变量CMAKE_C_FLAGS可以配置c编译器的编译选项;而设置变量CMAKE_CXX_FLAGS可配置针对c++编译器的编译选项。比如:
add_compile_options(-Wall -Wextra -pedantic -Werror)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -std=c99")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -std=c++11")
4 配置编译类型
通过设置变量CMAKE_BUILD_TYPE来配置编译类型,可设置为:Debug、Release、RelWithDebInfo、MinSizeRel等,比如:
set(CMAKE_BUILD_TYPE Debug)
当然,更好的方式应该是在执行cmake命令的时候通过参数-D指定:
cmake -B build -DCMAKE_BUILD_TYPE=Debug
如果设置编译类型为Debug,那么对于c编译器,CMake会检查是否有针对此编译类型的编译选项CMAKE_C_FLAGS_DEBUG,如果有,则将它的配置内容加到CMAKE_C_FLAGS中。
可以针对不同的编译类型设置不同的编译选项,比如对于Debug版本,开启调试信息,不进行代码优化:
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
对于Release版本,不包含调试信息,优化等级设置为2:
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
5 添加全局宏定义
通过命令add_definitions可以添加全局的宏定义,在源码中就可以通过判断不同的宏定义实现相应的代码逻辑。用法如下:
add_definitions(-DDEBUG -DREAL_COOL_ENGINEER)
6 添加include目录
通过命令include_directories来设置头文件的搜索目录,比如:
include_directories(src/c)
二 编译目标文件
一般来说,编译目标(target)的类型一般有静态库、动态库和可执行文件。这时编写CMakeLists.txt主要包括两步:
编译:确定编译目标所需要的源文件
链接:确定链接的时候需要依赖的额外的库
下面以开源项目(cmake-template)来演示。项目的目录结构如下:
./cmake-template
├── CMakeLists.txt
├── src
│ └── c
│ ├── cmake_template_version.h
│ ├── cmake_template_version.h.in
│ ├── main.c
│ └── math
│ ├── add.c
│ ├── add.h
│ ├── minus.c
│ └── minus.h
└── test
└── c
├── test_add.c
└── test_minus.c
项目的构建任务为:
将math目录编译成静态库,命名为math
编译main.c为可执行文件demo,依赖math静态库
编译test目录下的测试程序,可以通过命令执行所有的测试
支持通过命令将编译产物安装及打包
1 编译静态库
这一步需要将项目目录路径src/c/math下的源文件编译为静态库,那么需要获取编译此静态库需要的文件列表,可以使用set命令,或者file命令来进行设置。比如:
file(GLOB_RECURSE MATH_LIB_SRC src/c/math/*.c)
add_library(math STATIC ${MATH_LIB_SRC})
使用file命令获取src/c/math目录下所有的*.c文件,然后通过add_library命令编译名为math的静态库,库的类型是第二个参数STATIC指定的。
如果指定为SHARED则编译的就是动态链接库。
2 编译可执行文件
通过add_executable命令来往构建系统中添加一个可执行构建目标,同样需要指定编译需要的源文件。但是对于可执行文件来说,有时候还会依赖其他的库,则需要使用target_link_libraries命令来声明构建此可执行文件需要链接的库。
在示例项目中,main.c就使用了src/c/math下实现的一些函数接口,所以依赖于前面构建的math库。所以在CMakeLists.txt中添加以下内容:
add_executable(demo src/c/main.c)
target_link_libraries(demo math)
第一行说明编译可执行文件demo需要的源文件(可以指定多个源文件,此处只是以单个文件作为示例);第二行表明对math库存在依赖。
此时可以在项目的根目录下执行构建和编译命令,并执行demo:
➜ # cmake -B cmake-build
➜ # cmake --build cmake-build
➜ # ./cmake-build/demo
Hello CMake!
10 + 24 = 34
40 - 96 = -56
三 安装和打包
1 安装
对于安装来说,其实就是要指定当前项目在执行安装时,需要安装什么内容:
通过install命令来说明需要安装的内容及目标路径;
通过设置CMAKE_INSTALL_PREFIX变量说明安装的路径;
3.15往后的版本可以使用cmake --install --prefix <install-path>覆盖指定安装路径。
比如,在示例项目中,把math和demo两个目标按文件类型安装:
install(TARGETS math demo
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
这里通过TARGETS参数指定需要安装的目标列表;参数RUNTIME DESTINATION、LIBRARY DESTINATION、ARCHIVE DESTINATION分别指定可执行文件、库文件、归档文件分别应该安装到安装目录下个哪个子目录。
如果指定CMAKE_INSTALL_PREFIX为/usr/local,那么math库将会被安装到路径/usr/local/lib/目录下;而demo可执行文件则在/usr/local/bin目录下。
CMAKE_INSTALL_PREFIX在不同的系统上有不同的默认值,使用的时候最好显式指定路径。
同时,还可以使用install命令安装头文件:
file(GLOB_RECURSE MATH_LIB_HEADERS src/c/math/*.h)
install(FILES ${MATH_LIB_HEADERS} DESTINATION include/math)
假如将安装到当前项目的output文件夹下,可以执行:
➜ # cmake -B cmake-build -DCMAKE_INSTALL_PREFIX=./output
➜ # cmake --build cmake-build
➜ # cd cmake-build && make install && cd -
Install the project...
-- Install configuration: ""
-- Installing: .../cmake-template/output/lib/libmath.a
-- Installing: .../gitee/cmake-template/output/bin/demo
-- Installing: .../gitee/cmake-template/output/include/math/add.h
-- Installing: .../gitee/cmake-template/output/include/math/minus.h
可以看到安装了前面install命令指定要安装的文件,并且不同类型的目标文件安装到不同子目录。
2 打包
要使用打包功能,需要执行include(CPack)启用相关的功能,在执行构建编译之后使用cpack命令行工具进行打包安装;对于make工具,也可以使用命令make package。
打包的内容就是install命令安装的内容,关键需要设置的变量有:
变量 含义
CPACK_GENERATOR 打包使用的压缩工具,比如"ZIP"
CPACK_OUTPUT_FILE_PREFIX 打包安装的路径前缀
CPACK_INSTALL_PREFIX 打包压缩包的内部目录前缀
CPACK_PACKAGE_FILE_NAME 打包压缩包的名称,由CPACK_PACKAGE_NAME、CPACK_PACKAGE_VERSION、CPACK_SYSTEM_NAME三部分构成
比如:
include(CPack)
set(CPACK_GENERATOR "ZIP")
set(CPACK_PACKAGE_NAME "CMakeTemplate")
set(CPACK_SET_DESTDIR ON)
set(CPACK_INSTALL_PREFIX "")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
假如:CPACK_OUTPUT_FILE_PREFIX设置为/usr/local/package;CPACK_INSTALL_PREFIX设置为real/cool/engineer;CPACK_PACKAGE_FILE_NAME设置为CMakeTemplate-1.0.0;那么执行打包文件的生成路径为:
/usr/local/package/CMakeTemplate-1.0.0.zip
解压这个包得到的目标文件则会位于路径下:
/usr/local/package/real/cool/engineer/
此时重新执行构建,使用cpack命令执行打包:
➜ # cmake -B cmake-build -DCPACK_OUTPUT_FILE_PREFIX=`pwd`/output
➜ # cmake --build cmake-build
➜ # cd cmake-build && cpack && cd -
CPack: Create package using ZIP
CPack: Install projects
CPack: - Run preinstall target for: CMakeTemplate
CPack: - Install project: CMakeTemplate
CPack: Create package
CPack: - package: /Users/Farmer/gitee/cmake-template/output/CMakeTemplate-1.0.0-Darwin.zip generated.
cpack有一些参数是可以覆盖CMakeLists.txt设置的参数的,比如这里的-G参数就会覆盖变量CPACK_GENERATOR,具体细节可使用cpack --help查看。
四 测试
CMake的测试功能使用起来有几个步骤:
CMakeLists.txt中通过命令enable_testing()或者include(CTest)来启用测试功能;
使用add_test命令添加测试样例,指定测试的名称和测试命令、参数;
构建编译完成后使用ctest命令行工具运行测试。
为了控制是否开启测试,可使用option命令设置一个开关,在开关打开时才进行测试,比如:
option(CMAKE_TEMPLATE_ENABLE_TEST "Whether to enable unit tests" ON)
if (CMAKE_TEMPLATE_ENABLE_TEST)
message(STATUS "Unit tests enabled")
enable_testing()
endif()
这里为了方便后续演示,暂时是默认开启的。
1 编写测试程序
在此文的示例代码中,针对add.c和minus.c实现了两个测试程序,它们的功能是类似的,接受三个参数,用第一和第二个计算两个参数的和或者差,判断是否和第三个参数相等,如test_add.c的代码为:
// @Author: Farmer Li, 公众号: 很酷的程序员/RealCoolEngineer
// @Date: 2021-05-10
#include <stdio.h>
#include <stdlib.h>
#include "math/add.h"
int main(int argc, char* argv[]) {
if (argc != 4) {
printf("Usage: test_add v1 v2 expected\n");
return 1;
}
int x = atoi(argv[1]);
int y = atoi(argv[2]);
int expected = atoi(argv[3]);
int res = add_int(x, y);
if (res != expected) {
return 1;
} else {
return 0;
}
}
这里需要注意的是,对于测试程序来说,如果返回值非零,则表示测试失败。
2 添加测试
接下来先使用add_executable命令生成测试程序,然后使用add_test命令添加单元测试:
add_executable(test_add test/c/test_add.c)
add_executable(test_minus test/c/test_minus.c)
target_link_libraries(test_add math)
target_link_libraries(test_minus math)
add_test(NAME test_add COMMAND test_add 10 24 34)
add_test(NAME test_minus COMMAND test_minus 40 96 -56)
3 执行测试
现在重新执行cmake命令更新构建系统,执行构建,再执行测试:
➜ # cmake -B cmake-build
➜ # cmake --build cmake-build
➜ # cd cmake-build && ctest && cd -
Test project /Users/Farmer/gitee/cmake-template/cmake-build
Start 1: test_add
1/2 Test #1: test_add ......................... Passed 0.00 sec
Start 2: test_minus
2/2 Test #2: test_minus ....................... Passed 0.01 sec
100% tests passed, 0 tests failed out of 2
使用ctest -VV则可以看到更加详细的测试流程和结果。
在CMake 3.20往后的版本中,ctest可以使用--test-dir指定测试执行目录。
至此,一个较为完备的CMakeLists.txt就开发完成了。

86
cpp/common/box_sleep.hpp Normal file
View File

@ -0,0 +1,86 @@
#ifndef SLEEP_THREAD_HPP_
#define SLEEP_THREAD_HPP_
/*
* Sleep Sleep
*/
#include <thread>
#include <mutex>
namespace cpppub {
typedef class CThreadSleep
{
public:
CThreadSleep();
~CThreadSleep() = default;
public:
// 进入睡眠,不传入值使用默认值,传入则使用传入值。
void Sleep(int nMilliseconds = 0);
// 停止所有的 Sleep 睡眠,继续向下。
void Contiune();
// 设置默认的睡眠时长,不填写时其默认值为 10 ms, 如果传入 <= 0 值将使用默认的 10 ms。
void SetTimeOut(int nMilliseconds);
private:
bool getStatus() const;
private:
// 同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable
std::condition_variable m_Cv;
int m_nTimeOut; // 睡眠时间
const int m_nDefaultTimeOut = 10; // 默认睡眠时间
std::mutex m_Mutex; // 锁
bool m_bStopSleep; // 睡眠标志位
}ThreadSleep;
CThreadSleep::CThreadSleep()
{
m_bStopSleep = false;
m_nTimeOut = 10;
}
inline void CThreadSleep::Sleep(int nMilliseconds)
{
int nSleepTime = m_nTimeOut;
if (nMilliseconds > 0)
nSleepTime = nMilliseconds;
m_bStopSleep = false;
std::unique_lock<std::mutex> lock(m_Mutex);
std::chrono::system_clock::time_point nowtime = std::chrono::system_clock::now();
// 度过 timeout 时限后 函数求值为 false 则为 false,否则为 true。
// 若已度过时限,则求值并返回求值结果。
if (m_Cv.wait_until(lock, nowtime + (std::chrono::milliseconds(nSleepTime)),
[this] { return getStatus(); })) {
// 这里触发手动关闭
}
else {
// 这里触发超时
}
}
inline void CThreadSleep::Contiune()
{
m_bStopSleep = true;
m_Cv.notify_all();
}
inline void CThreadSleep::SetTimeOut(int nMilliseconds)
{
if (nMilliseconds <= 0)
m_nTimeOut = m_nDefaultTimeOut;
else
m_nTimeOut = nMilliseconds;
}
inline bool CThreadSleep::getStatus() const
{
return m_bStopSleep;
}
}
#endif // !SLEEP_THREAD_HPP_

View File

@ -0,0 +1,209 @@
#ifndef THREAD_POOL_HEADER
#define THREAD_POOL_HEADER
#include <condition_variable>
#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
namespace cppbox {
// 线程安全队列
template <typename T> class CQueueMt
{
public:
CQueueMt() = default;
CQueueMt(CQueueMt&& rh) noexcept {}
~CQueueMt() = default;
public:
// 返回队列是否为空
bool IsEmpty()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.empty();
}
// 返回队列数量
size_t Size()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.size();
}
// 添加元素
void Push(T& t)
{
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.emplace(t);
}
// 取出元素
bool Pop(T& t)
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_queue.empty())
return false;
t = std::move(m_queue.front());
m_queue.pop();
return true;
}
// 清除
void clear()
{
std::unique_lock<std::mutex> lock(m_mutex);
std::queue<T> queue;
std::swap(m_queue, queue);
}
private:
std::mutex m_mutex;
std::queue<T> m_queue;
};
class CBoxThreadPool
{
private:
class CWorker
{
public:
CWorker(CBoxThreadPool* pThreadPool, const size_t nID)
: m_nID(nID), m_pThreadPool(pThreadPool)
{
is_run_ = false;
}
// 重载操作
void operator()()
{
// 1.定义基础函数类 func
std::function<void()> func;
// 2.是否成功取出队列中的元素
bool have = false;
while (m_pThreadPool->is_start_ || !is_run_ || isContinue()) {
// 进入 while 后,标志位置成已进入。
is_run_ = true;
{
// 2.1 为线程环境加锁,互斥访问线程的休眠与唤醒
std::unique_lock<std::mutex> lock(m_pThreadPool->mutex_);
// 2.2 如果队列为空则阻塞并等待条件变量的通知
if (m_pThreadPool->m_queue.IsEmpty())
m_pThreadPool->cv_.wait(lock);
// 2.3 取出任务队列中的元素
have = m_pThreadPool->m_queue.Pop(func);
}
if (have)
func();
}
}
// 检查是否需要继续完成未完成的任务
bool isContinue()
{
if (!m_pThreadPool->is_wait_)
return false;
if (m_pThreadPool->m_queue.IsEmpty())
return false;
return true;
}
private:
size_t m_nID; // 工作ID
CBoxThreadPool* m_pThreadPool; // 所属线程池
bool is_run_; // 是否进入工作了
};
public:
explicit CBoxThreadPool(const int nThreadNum = 4)
: th_cnt_(nThreadNum),
is_start_(false),
is_wait_(false),
threads_(std::vector<std::thread>(nThreadNum))
{
}
~CBoxThreadPool() { ShutDownWaitCurrent(); }
CBoxThreadPool(const CBoxThreadPool&) = delete;
CBoxThreadPool(CBoxThreadPool&&) = delete;
CBoxThreadPool& operator=(const CBoxThreadPool&) = delete;
CBoxThreadPool& operator=(CBoxThreadPool&&) = delete;
public:
// 初始化线程池
void Init()
{
if (!is_start_) {
threads_.resize(th_cnt_);
for (size_t i = 0; i < threads_.size(); ++i) {
threads_.at(i) = std::thread(CWorker(this, i));
}
is_start_ = true;
is_wait_ = false;
return;
}
}
// 等待各线程当前任务完成然后关闭线程池
void ShutDownWaitCurrent()
{
if (!is_start_)
return;
is_wait_ = false;
is_start_ = false;
Close();
m_queue.clear();
}
// 等待所有已提交的任务完成然后关闭线程池
void ShutDownWaitAll()
{
if (!is_start_)
return;
is_wait_ = true;
is_start_ = false;
Close();
m_queue.clear();
}
// 向池子中提交一个待执行函数
template <typename F, typename... Args>
auto Submit(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
{
// 1. 创建一个绑定参数的函数,
// 连接函数和参数定义,特殊函数类型,避免左右值错误
std::function<decltype(f(args...))()> func =
std::bind(std::forward<F>(f), std::forward<Args>(args)...);
// 2. 使用智能指针以便调用拷贝构造
auto pTask =
std::make_shared<std::packaged_task<decltype(f(args...))()>>(func);
// 3. 包装进一个无参数函数
std::function<void()> rf = [pTask]() { (*pTask)(); };
// 4. 入队
m_queue.Push(rf);
// 5. 唤醒一个等待中的线程
cv_.notify_one();
// 6. 返回先前注册的任务指针
return pTask->get_future();
}
private:
void Close()
{
cv_.notify_all();
for (auto& m_thread : threads_) {
if (m_thread.joinable())
m_thread.join();
}
threads_.clear();
}
private:
int th_cnt_; // 线程数
bool is_start_; // 线程池是否启动
bool is_wait_; // 是否等待所有线程结束
std::mutex mutex_; // 线程休眠锁互斥
CQueueMt<std::function<void()>> m_queue;
std::vector<std::thread> threads_;
std::condition_variable cv_; // 环境锁,用于休眠或者唤醒
};
} // namespace cppbox
#endif

View File

@ -0,0 +1,147 @@
#include <windows.h>
#include <setupapi.h>
#include <tchar.h>
#include <stdio.h>
#include <string>
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"setupapi.lib")
//wchar_t * char2wchar(const char* cchar)
//{
// wchar_t *m_wchar;
// int len = MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), NULL, 0);
// m_wchar = new wchar_t[len + 1];
// MultiByteToWideChar(CP_ACP, 0, cchar, strlen(cchar), m_wchar, len);
// m_wchar[len] = '\0';
// return m_wchar;
//}
//
//char * wchar2char(const wchar_t* wchar)
//{
// char * m_char;
// int len = WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), NULL, 0, NULL, NULL);
// m_char = new char[len + 1];
// WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), m_char, len, NULL, NULL);
// m_char[len] = '\0';
// return m_char;
//}
BOOL DisableNetInterface(const std::string& szHardWareId, bool bStatus)
{
IN LPTSTR HardwareId;
//硬件ComponentId,注册表地址:system\currentcontrolset\class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0000
// HardwareId = L"PCI\\VEN_8086&DEV_0085&SUBSYS_13118086&REV_34";
HardwareId = (LPTSTR)szHardWareId.c_str();
DWORD NewState;
if (bStatus)
{
NewState = DICS_DISABLE;
//禁用
}
else
{
NewState = DICS_ENABLE;
//启用
}
//调用ddk函数,来禁用网卡
DWORD i, err;
BOOL Found = false;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA spDevInfoData;
//访问系统的硬件库
hDevInfo = SetupDiGetClassDevs(NULL, "PCI", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
//printf("访问系统硬件出错!");
return false;
}
//枚举硬件,获得需要的接口
spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++)
{
DWORD DataT;
LPTSTR p, buffer = NULL;
DWORD buffersize = 0;
//获得硬件的属性值
while (!SetupDiGetDeviceRegistryProperty(
hDevInfo,
&spDevInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize))
{
if (GetLastError() == ERROR_INVALID_DATA)
{
//不存在HardwareID. Continue.
break;
}
else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
//buffer size不对.
if (buffer)
LocalFree(buffer);
buffer = (LPTSTR)LocalAlloc(LPTR, buffersize);
}
else
{
//未知错误
goto cleanup_DeviceInfo;
}
}
if (GetLastError() == ERROR_INVALID_DATA)
continue;
//比较,找到和网卡ID相同的项
for (p = buffer; *p && (p < &buffer[buffersize]); p += lstrlen(p) + sizeof(TCHAR))
{
if (!_tcscmp(HardwareId, p))
{
//找到网卡
Found = TRUE;
break;
}
}
if (buffer)
LocalFree(buffer);
//如果相等
if (Found)
{
//禁用该设备
SP_PROPCHANGE_PARAMS spPropChangeParams;
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL;
spPropChangeParams.StateChange = NewState;
//禁用:DICS_DISABLE,DICS_ENABLE启用
//
if (!SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData, (SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(spPropChangeParams)))
{
DWORD errorcode = GetLastError();
}
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
{
DWORD errorcode = GetLastError();
}
switch (NewState)
{
case DICS_DISABLE:
printf("成功禁用网络!");
break;
case DICS_ENABLE:
printf("成功启用网络!");
break;
}
break;
}
}
//delete[] HardwareId;
//HardwareId = nullptr;
//退出时,清理工作环境
cleanup_DeviceInfo:
err = GetLastError();
SetupDiDestroyDeviceInfoList(hDevInfo);
SetLastError(err);
return true;
}

View File

@ -0,0 +1,64 @@
#ifndef CLOSE_PROCESS_HPP
#define CLOSE_PROCESS_HPP
/*
*
*/
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <algorithm>
char* Wchar2Char(const wchar_t* wp)
{
int len = WideCharToMultiByte(CP_ACP, 0, wp, wcslen(wp), NULL, 0, NULL, NULL);
char* m_char = new char[len + 1];
WideCharToMultiByte(CP_ACP, 0, wp, wcslen(wp), m_char, len, NULL, NULL);
m_char[len] = '\0';
return m_char;
}
BOOL KillProcessFromName(std::string strProcessName)
{
//创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照)
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//PROCESSENTRY32进程快照的结构体
PROCESSENTRY32 pe;
//实例化后使用Process32First获取第一个快照的进程前必做的初始化操作
pe.dwSize = sizeof(PROCESSENTRY32);
//下面的IF效果同:
//if(hProcessSnap == INVALID_HANDLE_VALUE) 无效的句柄
if (!Process32First(hSnapShot, &pe))
{
return FALSE;
}
//将字符串转换为小写
std::transform(strProcessName.begin(), strProcessName.end(), strProcessName.begin(), ::tolower);
//如果句柄有效 则一直获取下一个句柄循环下去
while (Process32Next(hSnapShot, &pe))
{
char* pszTem = Wchar2Char(pe.szExeFile);
//pe.szExeFile获取当前进程的可执行文件名称
std::string scTmp = std::string(pszTem);
delete[] pszTem;
//将可执行文件名称所有英文字母修改为小写
std::transform(scTmp.begin(), scTmp.end(), scTmp.begin(), ::tolower);
//scTmp.MakeLower();
//比较当前进程的可执行文件名称和传递进来的文件名称是否相同
//相同的话Compare返回0
if (scTmp == strProcessName)
{
//从快照进程中获取该进程的PID(即任务管理器中的PID)
DWORD dwProcessID = pe.th32ProcessID;
HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
::TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
return TRUE;
}
//scTmp.ReleaseBuffer();
}
//strProcessName.ReleaseBuffer();
return FALSE;
}
#endif

133
cpp/common/judge_ip.hpp Normal file
View File

@ -0,0 +1,133 @@
#ifndef W_PUBLIC_H_
#define W_PUBLIC_H_
#include <WinSock2.h>
#include <Iphlpapi.h>
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>
#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库
// 工程是否是 Unicode 编码
//#define CHARSET_UNICODE_DEFINE
namespace cpppub {
bool IsLocalIPExist(const char* pszIP)
{
bool isHave = false;
//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
auto pIpAdapterInfo = new IP_ADAPTER_INFO();
//得到结构体大小,用于GetAdaptersInfo参数
unsigned long stSize = sizeof(IP_ADAPTER_INFO);
//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
ULONG nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
delete pIpAdapterInfo;
// 这里的操作:重新分配是为了保证有足够的空间来进行存储。
pIpAdapterInfo = (IP_ADAPTER_INFO*)(new BYTE[stSize]);
nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
//记录网卡数量
int netCardNum = 0;
//记录每张网卡上的IP地址数量
int IPnumPerNetCard = 0;
PIP_ADAPTER_INFO header = pIpAdapterInfo;
if (ERROR_SUCCESS == nRel)
{
//输出网卡信息
//可能有多网卡,因此通过循环去判断
while (pIpAdapterInfo)
{
IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
do
{
if (strcmp(pIpAddrString->IpAddress.String, pszIP) == 0)
{
isHave = true;
break;
}
pIpAddrString = pIpAddrString->Next;
} while (pIpAddrString);
if (isHave)
break;
pIpAdapterInfo = pIpAdapterInfo->Next;
}
}
//释放内存空间
delete[] header;
return isHave;
}
char* Wchar2Char(const wchar_t* wp)
{
int len = WideCharToMultiByte(CP_ACP, 0, wp,
static_cast<int>(wcslen(wp)), nullptr, 0, nullptr, nullptr);
char* m_char = new char[len + 1];
WideCharToMultiByte(CP_ACP, 0, wp, static_cast<int>(wcslen(wp)), m_char, len, nullptr, nullptr);
m_char[len] = '\0';
return m_char;
}
void Wchar2CharFree(const char* pszChar)
{
delete[] pszChar;
}
BOOL KillProcessFromName(const std::string& strProcessName)
{
std::string szTemProcessName = strProcessName;
//创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照)
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//PROCESSENTRY32进程快照的结构体
PROCESSENTRY32 pe;
//实例化后使用Process32First获取第一个快照的进程前必做的初始化操作
pe.dwSize = sizeof(PROCESSENTRY32);
//下面的IF效果同:
//if(hProcessSnap == INVALID_HANDLE_VALUE) 无效的句柄
if (!Process32First(hSnapShot, &pe))
{
return FALSE;
}
//将字符串转换为小写
std::transform(szTemProcessName.begin(), szTemProcessName.end(), szTemProcessName.begin(), ::tolower);
//如果句柄有效 则一直获取下一个句柄循环下去
while (Process32Next(hSnapShot, &pe))
{
std::string scTmp;
// Unicode 编码时
// pe.szExeFile获取当前进程的可执行文件名称
#ifdef CHARSET_UNICODE_DEFINE
char* pszTem = Wchar2Char(pe.szExeFile);
scTmp = std::string(pszTem);
Wchar2CharFree(pszTem);
pszTem = nullptr;
#else
scTmp = std::string(pe.szExeFile);
#endif // CHARSET_UNICODE_DEFINE
//将可执行文件名称所有英文字母修改为小写
std::transform(scTmp.begin(), scTmp.end(), scTmp.begin(), ::tolower);
//scTmp.MakeLower();
//比较当前进程的可执行文件名称和传递进来的文件名称是否相同
//相同的话Compare返回0
if (scTmp == strProcessName)
{
//从快照进程中获取该进程的PID(即任务管理器中的PID)
DWORD dwProcessID = pe.th32ProcessID;
HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
::TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
return TRUE;
}
//scTmp.ReleaseBuffer();
}
//strProcessName.ReleaseBuffer();
return FALSE;
}
}
#endif

View File

@ -0,0 +1,86 @@
#include <iostream>
#include <string>
int main() {
int mscVersion = _MSC_VER;
mscVersion = mscVersion - mscVersion % 10;
std::string vcVersion;
std::string releaseDate;
std::string toolsetVersion;
std::string ideInfo;
if (mscVersion == 1200) {
vcVersion = "VC6.0 (Visual C++ 6.0)";
releaseDate = "1998";
toolsetVersion = "V60";
ideInfo = "MSVC++ 6.0";
} else if (mscVersion == 1300) {
vcVersion = "VC7.0 (Visual Studio 2002)";
releaseDate = "2002";
toolsetVersion = "V70";
ideInfo = "7.0";
} else if (mscVersion == 1310) {
vcVersion = "VC7.1 (Visual Studio 2003)";
releaseDate = "2003";
toolsetVersion = "V71";
ideInfo = "7.1";
} else if (mscVersion == 1400) {
vcVersion = "VC8.0 (Visual Studio 2005)";
releaseDate = "2005";
toolsetVersion = "V80";
ideInfo = "8.0";
} else if (mscVersion == 1500) {
vcVersion = "VC9.0 (Visual Studio 2008)";
releaseDate = "2008";
toolsetVersion = "V90";
ideInfo = "9.0";
} else if (mscVersion == 1600) {
vcVersion = "VC10.0 (Visual Studio 2010)";
releaseDate = "2010";
toolsetVersion = "V100";
ideInfo = "10.0";
} else if (mscVersion == 1700) {
vcVersion = "VC11.0 (Visual Studio 2012)";
releaseDate = "2012";
toolsetVersion = "V110";
ideInfo = "11.0";
} else if (mscVersion == 1800) {
vcVersion = "VC12.0 (Visual Studio 2013)";
releaseDate = "2013";
toolsetVersion = "V120";
ideInfo = "12.0";
} else if (mscVersion == 1900) {
vcVersion = "VC14.0 (Visual Studio 2015)";
releaseDate = "2015";
toolsetVersion = "V140";
ideInfo = "14.0";
} else if (mscVersion == 1910) {
vcVersion = "VC14.1 (Visual Studio 2017)";
releaseDate = "2017";
toolsetVersion = "V141";
ideInfo = "14.1";
} else if (mscVersion == 1920) {
vcVersion = "VC14.2 (Visual Studio 2019)";
releaseDate = "2019";
toolsetVersion = "V142";
ideInfo = "14.2";
} else if (mscVersion == 1930) {
vcVersion = "VC14.3 (Visual Studio 2022)";
releaseDate = "2022";
toolsetVersion = "V143";
ideInfo = "14.3";
} else {
vcVersion = "未知版本";
releaseDate = "未知";
toolsetVersion = "未知";
ideInfo = "未知";
}
std::cout << "VC版本: " << vcVersion << std::endl;
std::cout << "发布时间: " << releaseDate << std::endl;
std::cout << "工具集版本: " << toolsetVersion << std::endl;
std::cout << "IDE信息: " << ideInfo << std::endl;
return 0;
}

View File

@ -0,0 +1,99 @@
// 这里是其他函数实现的源Demo
#include <winsock2.h>
#include <iphlpapi.h>
#include <iostream>
int NetWorkInter()
{
//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO();
//得到结构体大小,用于GetAdaptersInfo参数
unsigned long stSize = sizeof(IP_ADAPTER_INFO);
//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
int nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
//记录网卡数量
int netCardNum = 0;
//记录每张网卡上的IP地址数量
int IPnumPerNetCard = 0;
if (ERROR_BUFFER_OVERFLOW == nRel)
{
//如果函数返回的是ERROR_BUFFER_OVERFLOW
//则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小
//这也是说明为什么stSize既是一个输入量也是一个输出量
//释放原来的内存空间
delete pIpAdapterInfo;
//重新申请内存空间用来存储所有网卡信息
pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize];
//再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量
nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
}
if (ERROR_SUCCESS == nRel)
{
//输出网卡信息
//可能有多网卡,因此通过循环去判断
while (pIpAdapterInfo)
{
std::cout << "网卡数量:" << ++netCardNum << std::endl;
std::cout << "网卡名称:" << pIpAdapterInfo->AdapterName << std::endl;
std::cout << "网卡描述:" << pIpAdapterInfo->Description << std::endl;
switch (pIpAdapterInfo->Type)
{
case MIB_IF_TYPE_OTHER:
std::cout << "网卡类型:" << "OTHER" << std::endl;
break;
case MIB_IF_TYPE_ETHERNET:
std::cout << "网卡类型:" << "ETHERNET" << std::endl;
break;
case MIB_IF_TYPE_TOKENRING:
std::cout << "网卡类型:" << "TOKENRING" << std::endl;
break;
case MIB_IF_TYPE_FDDI:
std::cout << "网卡类型:" << "FDDI" << std::endl;
break;
case MIB_IF_TYPE_PPP:
printf("PP\n");
std::cout << "网卡类型:" << "PPP" << std::endl;
break;
case MIB_IF_TYPE_LOOPBACK:
std::cout << "网卡类型:" << "LOOPBACK" << std::endl;
break;
case MIB_IF_TYPE_SLIP:
std::cout << "网卡类型:" << "SLIP" << std::endl;
break;
default:
break;
}
std::cout << "网卡MAC地址:";
for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++)
if (i < pIpAdapterInfo->AddressLength - 1)
{
printf("%02X-", pIpAdapterInfo->Address[i]);
}
else
{
printf("%02X\n", pIpAdapterInfo->Address[i]);
}
std::cout << "网卡IP地址如下:" << std::endl;
//可能网卡有多IP,因此通过循环去判断
IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
do
{
std::cout << "该网卡上的IP数量:" << ++IPnumPerNetCard << std::endl;
std::cout << "IP 地址:" << pIpAddrString->IpAddress.String << std::endl;
std::cout << "子网地址:" << pIpAddrString->IpMask.String << std::endl;
std::cout << "网关地址:" << pIpAdapterInfo->GatewayList.IpAddress.String << std::endl;
pIpAddrString = pIpAddrString->Next;
} while (pIpAddrString);
pIpAdapterInfo = pIpAdapterInfo->Next;
std::cout << "--------------------------------------------------------------------" << std::endl;
}
}
//释放内存空间
if (pIpAdapterInfo)
{
delete pIpAdapterInfo;
}
return 0;
}

93
cpp/error/cpp_err.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "cpp_err.h"
#include <string>
#ifdef _MSC_VER
#include "windows.h"
#include "DbgHelp.h"
#endif
void stackoverflow()
{
// 1.线程栈空间有上限: windows 默认:1MB,Linux默认 2MB。
// 2.当前线程占用栈空间大小:线程函数调用堆栈中各个函数占用的栈空间总和。
// 3.哪些对象占用了栈空间:
// (1)函数局部变量
// (2)调用函数的参数
// 4.常见引发栈溢出的原因:
// (1)递归太深
// (2)局部变量占用太大
// (3)switch-case case分支过多。
// (4)死循环调用
// 5.发生线程栈溢出时,VS可能直接退出,无法看到调用堆栈,可以使用WinDBG查看。
}
#ifdef _MSC_VER
int GenerateMiniDump(PEXCEPTION_POINTERS pExceptionPointers, const std::string& dump_dir)
{
// 定义函数指针
typedef BOOL(WINAPI * MiniDumpWriteDumpT)(
HANDLE,
DWORD,
HANDLE,
MINIDUMP_TYPE,
PMINIDUMP_EXCEPTION_INFORMATION,
PMINIDUMP_USER_STREAM_INFORMATION,
PMINIDUMP_CALLBACK_INFORMATION
);
// 从 "DbgHelp.dll" 库中获取 "MiniDumpWriteDump" 函数
MiniDumpWriteDumpT pfnMiniDumpWriteDump = NULL;
HMODULE hDbgHelp = LoadLibrary("DbgHelp.dll");
if (NULL == hDbgHelp)
{
return EXCEPTION_CONTINUE_EXECUTION;
}
pfnMiniDumpWriteDump = (MiniDumpWriteDumpT)GetProcAddress(hDbgHelp, "MiniDumpWriteDump");
if (NULL == pfnMiniDumpWriteDump)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 创建 dmp 文件
char path_buffer[512]{};
char szVersion[] = "DumpDemo_v1.0";
SYSTEMTIME stLocalTime;
GetLocalTime(&stLocalTime);
std::snprintf(path_buffer, sizeof(path_buffer), "%s\\%s-%04d%02d%02d-%02d%02d%02d.dmp", dump_dir.c_str(),
szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond);
HANDLE hDumpFile = CreateFile(path_buffer, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
if (INVALID_HANDLE_VALUE == hDumpFile)
{
FreeLibrary(hDbgHelp);
return EXCEPTION_CONTINUE_EXECUTION;
}
// 写入 dmp 文件
MINIDUMP_EXCEPTION_INFORMATION expParam;
expParam.ThreadId = GetCurrentThreadId();
expParam.ExceptionPointers = pExceptionPointers;
expParam.ClientPointers = FALSE;
pfnMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, (pExceptionPointers ? &expParam : NULL), NULL, NULL);
// 释放文件
CloseHandle(hDumpFile);
FreeLibrary(hDbgHelp);
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ExceptionFilter(LPEXCEPTION_POINTERS lpExceptionInfo)
{
// 这里做一些异常的过滤或提示
if (IsDebuggerPresent())
{
return EXCEPTION_CONTINUE_SEARCH;
}
return GenerateMiniDump(lpExceptionInfo, "D:\\");
}
// windows cpp 崩溃使用 windbg 调试
void use_windbg()
{
SetUnhandledExceptionFilter(ExceptionFilter);
}
#endif

9
cpp/error/cpp_err.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
// 线程栈溢出
void stackoverflow();
#ifdef _MSC_VER
// windows cpp 崩溃使用 windbg 调试
void use_windbg();
#endif

29
cpp/export_c/ex_lib.cpp Normal file
View File

@ -0,0 +1,29 @@
#include "ex_lib.h"
#include "my_math.h"
#include <new>
struct math_struct {
my_math impl;
};
extern "C"
math_struct* create()
{
return new(std::nothrow) math_struct;
}
extern "C"
int get_sum(struct math_struct* ms, int a, int b)
{
if (!ms)
return -1;
return ms->impl.GetSum(a, b);
}
extern "C"
void free_math(struct math_struct* ms)
{
if (!ms)
return;
delete ms;
}

19
cpp/export_c/ex_lib.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef EX_LIB_H_
#define EX_LIB_H_
#if __cplusplus
extern "C" {
#endif
struct math_struct;
math_struct* create();
int get_sum(struct math_struct* ms, int a, int b);
void free_math(struct math_struct* ms);
#if __cplusplus
}
#endif
#endif // !_EX_LIB_H_

10
cpp/export_c/main.cpp Normal file
View File

@ -0,0 +1,10 @@
#include <cstdio>
#include "ex_lib.h"
int main()
{
math_struct* pMath = create();
printf("23 + 56 = %d\n", get_sum(pMath, 23, 56));
free_math(pMath);
return 0;
}

6
cpp/export_c/my_math.cpp Normal file
View File

@ -0,0 +1,6 @@
#include "my_math.h"
int my_math::GetSum(int a, int b) const
{
return a + b + m_nBase;
}

13
cpp/export_c/my_math.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
class my_math
{
private:
int m_nBase {6};
public:
my_math() = default;
~my_math() = default;
public:
int GetSum(int a, int b) const;
};

View File

@ -1,22 +0,0 @@
1.ssh配置免访问文件:authorized_keys
2.apt设置临时代理:
sudo apt-get -o Acquire::http::proxy="socks5h://192.168.0.102:7890/" install mariadb-server
3.CentOS7 升级GCC
(3.1) rpm -q gcc
(3.2) rpm -e [第二步查到的版本号]
如果
error: Failed dependencies:
gcc = 4.4.7-23.el6 is needed by (installed) gcc-c++-4.4.7-23.el6.x86_64
gcc = 4.4.4 is needed by (installed) libtool-2.2.6-15.5.el6.x86_64
rpm -e gcc-c++-4.4.7-23.el6.x86_64
rpm -e libtool-2.2.6-15.5.el6.x86_64
验证卸载:
[root@123 /]# gcc -v
-bash: /usr/bin/gcc: No such file or directory
[root@123 /]# g++ -v
-bash: /usr/bin/g++: No such file or directory
yum install centos-release-scl
yum install -y devtoolset-11-gcc devtoolset-11-gcc-c++
scl enable devtoolset-11 bash
vim /etc/profile
PATH=$PATH::/opt/rh/devtoolset-11/root/usr/bin

147
linux/Linux-base.txt Normal file
View File

@ -0,0 +1,147 @@
1.ssh配置免访问文件:authorized_keys
2.apt设置临时代理:
sudo apt-get -o Acquire::http::proxy="socks5h://192.168.0.102:7890/" install mariadb-server
3.CentOS7 升级GCC
(3.1) rpm -q gcc
(3.2) rpm -e [第二步查到的版本号]
如果
error: Failed dependencies:
gcc = 4.4.7-23.el6 is needed by (installed) gcc-c++-4.4.7-23.el6.x86_64
gcc = 4.4.4 is needed by (installed) libtool-2.2.6-15.5.el6.x86_64
rpm -e gcc-c++-4.4.7-23.el6.x86_64
rpm -e libtool-2.2.6-15.5.el6.x86_64
验证卸载:
[root@123 /]# gcc -v
-bash: /usr/bin/gcc: No such file or directory
[root@123 /]# g++ -v
-bash: /usr/bin/g++: No such file or directory
yum install centos-release-scl
yum install -y devtoolset-11-gcc devtoolset-11-gcc-c++
scl enable devtoolset-11 bash
vim /etc/profile
PATH=$PATH::/opt/rh/devtoolset-11/root/usr/bin
==>Debian系列安装后的网卡配置:
1.U盘安装一个无线网卡驱动包。
2.然后需要链接有线安装两个组件:net-tools wireless-tools
sudo apt install xxx
3.安装完毕之后查看无线网卡的信息,例如名称为: wlan0
4.配置netplan,(之前网上讲的是/etc/network/interface,在这里不是)
在/etc/netplan/目录下有yaml文件,可以查看是哪个里面配置了网卡信息。
默认内容是:
network:
ethernets:
ehth0:
dhcp4: true
optional: true
version 2
在这里添加(最外层跟ethernets对齐):
renderer: networkd
wifis:
wlan0:
dhcp4: true
access-points:
"xxxwifiname":
password: "xxxxwifipasswd"
5.使用sudo netplan apply启用。
配置文件
/etc/systemd/logind.conf
配置说明
HandlePowerKey: 按下电源键后的行为,默认power off
HandleSleepKey: 按下挂起键后的行为,默认suspend
HandleHibernateKey: 按下休眠键后的行为,默认hibernate
HandleLidSwitch: 合上笔记本盖后的行为,默认suspend
只监视带有 “power-switch” 标签的 输入设备的 key(按下按钮)/lid(合上盖子) 事件。
如果主机插入了一个扩展坞(docking station) 或者连接了多个显示器, 那么"合上盖子"将执行 HandleLidSwitchDocked= 动作;
如果主机使用外部电源, 并且 HandleLidSwitchExternalPower= 不是默认值(“ignore”), 那么"合上盖子"将执行 HandleLidSwitchExternalPower= 动作; 否则将执行 HandleLidSwitch= 动作。
参数说明
ignore(无操作),
poweroff(关闭系统并切断电源),
reboot(重新启动),
halt(关闭系统但不切断电源),
kexec(调用内核"kexec"函数),
suspend(休眠到内存),
hibernate(休眠到硬盘),
hybrid-sleep(同时休眠到内存与硬盘),
suspend-then-hibernate(先休眠到内存超时后再休眠到硬盘),
lock(锁屏)
设置笔记本合并盖子不休眠
编辑文件/etc/systemd/logind.conf
#HandleLidSwitch=suspend
1
注意前面的 # 也要去掉
修改为(无操作)
HandleLidSwitch=ignore
1
或(锁屏)
HandleLidSwitch=lock
1
重启服务
service systemd-logind restart
1
文章知识点与官方知识档
————————————————
版权声明:本文为CSDN博主「猫巳」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_31635851/article/details/124627990
Q1: Qt5 安装之后无法打开,那么就在cmd命令行中,设置 export QT_DEBUG_PLUGINS=1
然后启动应用程序,会报相信的错误信息,一般是缺少各种库,比如libqxcb依赖的库有的没有,则使用
ldd libqxcb.so
查看具体哪些没有,然后使用 apt search xxxx 这些没有的库,最后安装。
Q2: 设置iBus中文输入法
为什么使用iBus输入法,因为fcitx有很多兼容性问题。
# 彻底卸载sogou和fcitx
sudo apt purge sogoupinyin
sudo apt purge fcitx
sudo apt autoremove
sudo apt remove fcitx*
sudo apt purge fcitx*
sudo apt autoremove
# 删除配置文件
cd .config/
rm -rf sogoupinyin/
rm -rf ibus
# 安装ibus
sudo apt install ibus ibus-sunpinyin
Q3: 键盘功能键设置失效问题
echo options hid_apple fnmode=2 | sudo tee -a /etc/modprobe.d/hid_apple.conf
sudo update-initramfs -u -k all
sudo reboot
# Debian/Ubuntu/Mint
sudo apt install initramfs-tools
# the "-k all" part is not always needed, but it's better to do that for all kernels anyway
sudo update-initramfs -u -k all
# RedHat/Fedora/CentOS
sudo dracut --regenerate-all --force 作者:大敏鸽 https://www.bilibili.com/read/cv16950091 出处:bilibili
R1: 使用 plank 作为 dock 坞
sudo apt-get install pavucontrol
安装远程桌面
sudo apt-get install tightvncserver xrdp
秘钥
ssh-keygen
pub公钥>>authorized_keys

310
linux/Linux-knowledge.txt Normal file
View File

@ -0,0 +1,310 @@
ctrl+p 上一个命令,ctrl+n 下一个命令
ctrl+b 光标回移, ctrl+f 向后移动, ctrl+a 行首, ctrl+e 行尾
ctrl+h 删除前, ctrl+d 删除后。Linux中光标盖住的是后一个字符。
ctrl+u 删除光标前面所有。ctrl+l 清屏。
vim 基础操作:
j :下移一行
k :上移一行
h :左移一个字符
l :右移一个字符
gg :跳到第一行
G :跳到最后一行
0 :左移到行首
$ :右移到行尾
ctrl + f :向下翻页
ctrl + b :向上翻页
ctrl + d :向下翻半页( d 代表 down )
ctrl + u :向上翻半页( u 代表 up )
H :移动到屏幕最上面(页面本身不动)( H 代表 high )
L :移动到屏幕最下面(页面本身不动)( L 代表 low )
M :移动到屏幕中间行(页面本身不动)( M 代表 middle )
zt :把当前行移动到屏幕最上面( t 代表 top )
zb :把当前行移动到屏幕最下面( b 代表 bottom )
z. :把当前行移动到屏幕中间
:<n> :跳到第 <n> 行(需要回车)
ls 可传一个目录参数。
Liunx的目录结构:
/bin: 常用命令
/boot: 启动系统的核心文件
/dev: Linux的外部设备,访问设备与访问文件的方式是一样的。
/etc: 系统管理所需要的配置文件和子目录。
/home: 用户目录。
/lib: 库文件。
/lost+found: 一般是空的,非法关机之后存放一些文件。
/media: Linux会自动识别一些设备,如U盘,自动挂载到Media下面。
/mnt: 让用户临时挂载别的文件系统时用。
/opt: 给主机额外安装软件所摆放的目录, 默认为空。
/proc: 虚拟的目录,内存的映射,可以直接访问这个目录来获取系统信息。
这个目录的内容不在硬盘而是在内存中, 可以直接修改。
/root: 超级用户目录。
/sbin: 系统管理员的程序。
/selinux: 是Redhat/Centos特有的一个安全机制,类似防火墙。
/srv: 服务启动之后需要提取的数据。
/sys: Liunx2.6内核的大变化
/tmp: 存放临时文件。
/usr: 很多用户程序和文件放在这里。
/usr/bin: 系统用户程序。
/usr/sbin: 超级用户使用的比较高级的管理程序和系统守护程序。
/usr/src: 内核代码默认放置目录。
/var: 存放不断扩充的东西,比如各种日志文件。
cd -: 切换到临近目录。
yun@debian:
yun是当前登录的用户名,debian是安装系统时设置的主机名。
$: 普通用户
#: 超级用户
直接cd,回家目录。
创建软链接:
ln -s /home/yun/hello.c /home/yun/hello.soft
ln -s /home/yun/download xxx.soft
创建硬链接(并没有拷贝):
ln /home/yun/hello.c hello.hard
wc: 获取文本文件的行数,单词数,字符数。
od: 查看二进制文件,od -t 指定显示格式。
du: 查看当前目录的大小。du -h
-rw-rw-r--,-文件,rw-文件所有者权限,rw-所属组权限。r--其他人权限。
chmod:
1.文字设定,[who]文件所有者u, 文件所属组g, 其他人o, 所有人a
+-= (增减覆盖) [mode]读r,w写,x执行。
2.数字设定,r->4, w->2, x->1, chmod -001 xxx
修改文件所属组所有者:
chown Lisi main.cpp 所有者变了,但是所有组没有变化。
chown Zhangsan:group2 都变了。
chgrp 仅修改所有组。chgrp group3 xxx.cpp
mkfifo 创建管道
所有的目录能查看和进入,必须有x,可执行权限。
find [path] -name "xxx.cpp"
?: 通配一个字符
*: 通配所有字符。
find [path] -size +10k[-10 k,M,]
查找范围,多个-size即可。
find [path] -type d
文件类型-所有者权限-同组用户权限-其他人权限-硬链接数-所有者-所属组-占用-时间
Linux 文件类型:
-: 普通文件(f)
d: 目录
l: 链接符
b: 块设备
c: 字符设备
s: socket设备
p: 管道
卸载硬盘:umount /media/user/xxx-usb
sudo fdisk -l 查看设备信息。比如U盘是/dev/sdb
挂载硬盘:mount devicename /mnt
sd->SCSI Device
hd->Hard Disk
fd->Floppy Disk
主分区最多有4个。sda4
压缩相关:
gzip 打包:g(un)zip *.txt ->xxx.gz 文件
b(un)zip2 *.txt 都不会保留原文件,没有打包压缩。->bz2文件
tar: c-创建,x-解压缩, v-显示信息, f-指定名字,
z-使用gzip的方式压缩,j-使用bzip2的方式压缩,不添加zj只能打包。
压缩:tar zcvf xxx -> xxx.tar.gz tar jcvf xxx -> xxx.tar.bz2
完整示例:tar zcvf result.tar.gz *.txt
解压到指定目录:
tar zxvf xxx.tar.gz -C /home/yun/test/
终端[文字终端][图形界面终端]
tty1->tty6 tty7
who
pts: 设备终端
PID 进程的ID
ps [a 查看当前所有用户][u 显示用户的信息][x 查看没有终端的应用程序]
使用管道重定向(|){输出作为另外一个命令的输入}
ps aux | grep bash
kill -l 查看信号
kill -SIGKILL 2351 或者 kill -9 8311 也可以
env 环境变量
网络相关命令:
ip addr, ping [-c 4 -i xx s], ifconfig,
nslookup www.baidu.com 查看IP地址。
用户的添加:
adduser (脚本) + Zhangsan
useradd (命令)
su Zhangsan 切换用户
useradd [-s 什么解析器(/bin/bash)][-g 所属组(Robin)][-d 目录(/home/xxx)]
[-m 如果没有xxx目录就创建Robin]
groupadd xxxGroup 增加组
passwd Zhangsan 修改密码
删除用户:deluser, userdel -r
/etc/passwd下可以查看用户
vsftpd: FTP服务器的一个软件。
service xxx restart
lftp: 可以上传和下载目录。
alias: 查看命令是否被封装
ldd: 查看so文件依赖。
Linux会优先搜索LD_LIBRARY_PATH,之后再去默认位置查找。
也可以设置:/etc/ld.so.conf, ldconfig更新生效。
gdb xxx
l 查看源码,包含main函数的文件。
否则 l qimen.c:20 查看这块代码
l qimen.c:run 也可以。
继续查看后面的继续输入l或者直接回车。
break xxx行(b 行) 普通断点。
特殊断点:b 20 if i==15
i b: 查看断点信息。(info break)
start开始运行,执行一步。
r 直接跑。[run]
单步调试:n, 直接到断点:c (continue)
进入函数:s (step)
p 打印值。
ptype 查看变量类型。
display i 追踪变量i的值。
undisplay 变量编号取消追踪。
u 跳出单次循环
finish 跳出进入的函数体。取消里面的断点才可以退出。
d 编号删除断点。[del]
set var i=10 设置变量的值。
quit 退出。
Makefile的编写:
三要素:目标,依赖,命令。 --> 一条规则
result: sub.h sub.cpp
g++ main.cpp sub.h sub.cpp -o result
分开编译,防止每次全部编译。
math.o: sub.cpp
g++ -c sub.cpp
main.o: main.cpp
g++ -c main.cpp
result: main.o math.o
g++ -o result main.o math.o
Makefile中的变量。
obj=main.o math.o
result: $(obj)
g++ -o result $(obj)
vim 替换:3,4s/prestr/afterstr
makefile语法一样的情况:
{模式规则}
%.o:%.c
g++ -c $< -o $@
原理:
1.例如依赖sub.o,那么%.o中的%就对应成了sub,
即sub.o: sub.c
2.$<: 自动变量, 规则中的第一个依赖。
$@: 规则中的目标。
$^: 规则中的所有依赖。
以上只能在命令模式中使用。
一般:CPPFLAGS:预处理器需要的参数,例如: -I
CFLAGS:编译参数,例如: -Wall
LDFLAGS:链接库参数,例如: -L
makefile中的函数,所有的函数都有返回值。
src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
.PHONY:clean 声明伪目标,不检查文件。
-rm [-]如果当前命令失败,继续执行。
全局变量不初始化=0,局部的未知。
FILE* 结构体:文件描述符,读写指针,I/O缓冲区(addr)de:8KB
Linux 启动一个进程后内存模型:{虚拟地址}
虚拟地址作用:1.空间隔离 2.访问不连续物理空间 3.物理内存分配。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Linux kernel[内存管理,进程管理,设备驱动管理,文件系统]
| 内核区32位是,3G~4G
环境变量
命令行参数
栈(向下增长)
共享库
堆(向上增长)
>>>>>>>>>
.bss未初始化变量
.data已初始化变量
xxx 其他
.text代码段
>>>>>>>>> ELF段
受保护的地址(0~4K)。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
PCB进程控制块。文件描述符表[一个数组]。
默认打开了三个,标准输入输出错误。
打开一个文件占用一个描述符,最小占用原则。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
file xxx可以查看xxx信息。
C库函数与系统函数之间的关系:
例如[printf]
->系统API(应用层write)
->系统调用(sys_write) {用户空间到内核空间转换}
->内核层(驱动)
->硬件显示。
Linux系统IO函数:open, read, write, lseek 可使用man文档。
man 章节号 open
errno 全局变量
perror(const char* s)[stdio.h]
open系统函数中指定的权限与umask掩码取反做一个按位与的操作。
在vim中,可以直接使用K查看函数文档。
守护进程
1.后台服务
2.不受登录注册影响
3.一般以d结尾。
4.周期性执行任务
5.独立于终端
简述秘钥使用方法:
非对称加密算法:加密使用的密钥和解密使用的密钥是不同的。 公钥密码体制就是一种非对称加密算法
私钥,公钥。服务器持有公钥,本地私钥可以登录。
加密解密过程如下:
加密:通过加密算法和公钥对内容(或者说明文)进行加密,得到密文。
解密:通过解密算法和私钥对密文进行解密,得到明文。
注意:由公钥加密的内容,只能由私钥进行解密。
服务:[debian]
/etc/systemd/system/
xxx.service
[Unit]
Description=EyeblueTank
Documentation=https://tank-doc.eyeblue.cn
Wants=network.target
After=network.target mariadb.service
[Service]
Type=simple
ExecStart=/home/yun/program/tank/tank
[Install]
WantedBy=multi-user.target
# 装载tank服务
systemctl daemon-reload
# 设置tank开机启动
systemctl enable tank.service
# 查看tank状态
systemctl status tank.service
# 启动tank
systemctl start tank.service
# 重启tank
systemctl restart tank.service
# 停止tank
systemctl stop tank.service
1.安装mariadb 记录安装版本为10.5
sudo apt-get install mariadb-server
sudo mysql_secure_installation设置密码即可。
CREATE DATABASE boys CHARACTER SET = utf8 COLLATE = utf8_general_ci;
neofetch

185
qt/QtCompilerConfigure.txt Normal file
View File

@ -0,0 +1,185 @@
1.configure meta:
-help,-h ............显示此帮助屏幕
-verbose,-v .........在配置期间输出详细消息
-continue............尽管有错误仍然继续配置
-redo ................用以前使用的选项重新配置。其他选项可能会通过,但不会保存以供-redo稍后使用。
-recheck .............放弃缓存的负配置测试结果。安装缺失的依赖关系后使用它。
-recheck-all .........放弃所有缓存的配置测试结果。
-feature- <特征> ...启用<特征>
-no-feature- <feature>禁用<feature> [none]
-list-features .......列出可用功能。请注意一些功能也有专用的命令行选项。
-list-libraries ......列出可能的外部依赖关系。
2.Build options:
-opensource ..........构建Qt的开源版本
-commercial ..........构建Qt的商业版
-confirm-license .....自动确认许可证
-release.............关闭调试版本的Qt [yes]
-debug ...............打开调试生成Qt [no]
-debug-and-release ...构建两个版本的Qt,包含和不包含打开调试[是](仅适用于Apple和Windows)
-optimize-debug ......在调试版本中启用调试友好的优化[自动](MSVC不支持)
-optimize-size .......优化发布版本的大小而不是速度[no]
-optimized-tools .....甚至在调试版本中构建优化的主机工具[no]
-force-debug-info ....为发布版本创建符号文件[no]
-separate-debug-info。分离调试信息以分离文件[no]
-strip ...............释放不需要的符号的二进制文件[是]
-force-asserts .......即使在发布版本中启用Q_ASSERT [no]
-developer-build .....编译并链接Qt以开发Qt本身(用于自动测试的出口,额外检查等)[no]
-shared..............建立共享的Qt库[是](不适用于UIKit)
-static ..............构建静态Qt库[no](对于UIKit是)
-framework ...........构建Qt框架包[是](仅限Apple)
-platform <target> ...选择主机mkspec [检测到]
-xplatform <target> ..交叉编译时选择target mkspec [PLATFORM]
-device <name> .......交叉编译设备<name>
-device-option <key = value> ...为设备mkspec添加选项
-appstore-compliant ..禁用平台应用商店中不允许使用的代码。默认情况下,默认情况下,默认情况下,平台需要通过默认应用商店进行分发,特别是Android,iOS,tvOS,watchOS和Universal Windows Platform。 [汽车]
-qtnamespace <name> ..将所有Qt库代码封装在'namespace <name> {...}'中。
-qtlibinfix <infix>将所有libQt5 * .so重命名为libQt5 * <infix> .so。
-testcocoon ..........带有TestCocoon代码覆盖工具的仪器[no]
-gcov ................具有GCov代码覆盖工具的仪器[no]
-sanitize {address | thread | memory | undefined}仪器与指定的编译器消毒剂。
-c ++ std <edition> ....选择C ++标准<edition> [c ++ 1z / c ++ 14 / c ++ 11](不支持MSVC)
-sse2 ................使用SSE2指令[自动]
-sse3 / -ssse3 / -sse4.1 / -sse4.2 / -avx / -avx2 / -avx512启用特定的x86指令[auto]启用的仍然受到运行时检测。
-mips_dsp / -mips_dspr2使用MIPS DSP / rev2指令[auto]
-qreal <type> ........ typedef qreal到指定的类型。 [双]注意:这会影响二进制兼容性。
-R <string> ..........为Qt添加一个显式的运行时库路径库。支持相对于LIBDIR的路径。
-rpath ...............使用库链接Qt库和可执行文件将路径安装为运行时库路径。如同-R LIBDIR。在苹果平台上,禁用这意味着使用绝对安装名称(基于 LIBDIR)动态库和框架。 [汽车]减少输出......减少输出符号的数量[自动]
-reuce-relocations ..减少重定位量[auto](仅适用于Unix)
-plugin-manifests ....将清单嵌入插件[no](仅限Windows)
-static-runtime ......使用-static,使用静态运行时[no](仅限Windows)
-pch .................使用预编译头文件[auto]
-ltcg ................使用链接时间码生成[no]
-use-gold-linker .....使用GNU gold链接器[auto]
-incredibuild-xge ....使用IncrediBuild XGE [no](仅限Windows)
-ccache ..............使用ccache编译器缓存[no](仅适用于Unix)
-make-tool <tool> ....使用<tool>构建qmake [nmake](仅适用于Windows)
-mp ..................使用多个处理器进行编译(仅限MSVC)
-warnings-are-errors。将警告视为错误[no; yes如果-developer-build]
-silent ..............减少构建输出以便发出警告和错误可以更容易地看到
3.Build environment:
-sysroot <dir> ....... 将<dir>设置为目标sysroot
-gcc-sysroot ......... 使用-sysroot,将编译器通过--sysroot [yes]
-pkg-config ..........使用pkg-config [auto](仅适用于Unix)
-D <string> ..........传递附加的预处理器定义
-I <string> ..........传递额外的包含路径
-L <string> ..........传递额外的库路径
-F <string> ..........传递额外的框架路径(仅适用于Apple)
-sdk <sdk> ...........使用Apple提供的SDK <sdk>构建Qt。争论应该是以下列出的可用SDK之一'xcodebuild -showsdks'。请注意,该参数仅适用于Qt库和使用目标mkspec构建的应用程序 - 不是主机工具,如qmake,moc,rcc等。
-android-sdk path ....设置Android SDK根路径[$ ANDROID_SDK_ROOT]
-android-ndk路径....设置Android NDK根路径[$ ANDROID_NDK_ROOT]
-android-ndk-platform设置Android平台
-android-ndk-host ....设置Android NDK主机(linux-x86,linux-x86_64等)[$ ANDROID_NDK_HOST]
-android-arch ........设置Android体系结构(armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64)
-android-toolchain-version ...设置Android工具链版本
-android-style-assets自动从设备中提取样式资产运行。此选项使Android样式表现良好正确的,但也使得Android平台插件与LGPL2.1不兼容。 [是]
4.Component selection:
-skip <repo> .........从构建中排除整个存储库。
-make <part> .........将<part>添加到要构建的零件列表中。指定此选项将首先清除默认列表。[库和例子,如果不是交叉构建也是工具,还测试是否 -
开发人员构建]
-nomake <part> .......从要构建的零件列表中排除<part>。
-compile-examples ....未设置时,只安装示例的源代码[是]
-gui .................构建Qt GUI模块和依赖[yes]
-widgets .............编译Qt Widgets模块和依赖[yes]
-no-dbus .............不要构建Qt D-Bus模块[Android和Windows默认]
-dbus-linked .........构建Qt D-Bus并链接到libdbus-1 [auto]
-dbus-runtime ........构建Qt D-Bus并动态加载libdbus-1 [no]
-accessibility.......启用可访问性支持[是]注意:不建议禁用可访问性。
-qml-debug ...........启用QML调试支持[yes]
Qt附带一些第三方库的捆绑副本。这些被使用默认情况下,如果自动检测相应的系统库失败。
5.Core options:
-doubleconversion ....选择使用的双转换库[system / qt / no]没有暗示使用sscanf_l和snprintf_l(不精确)。
-glib ................启用Glib支持[no;在Unix上自动]
-eventfd .............启用eventfd支持
-inotify .............启用inotify支持
-iconv ...............启用iconv(3)支持[posix / sun / gnu / no](仅适用于Unix)
-icu .................启用ICU支持[自动]
-pcre ................选择使用的libpcre2 [system / qt]
-pps .................启用PPS支持[自动](仅限QNX)
-zlib ................选择用过的zlib [system / qt]
6.Logging backends:
-Journald ..........启用日志支持[no](仅限Unix)
-syslog ............启用syslog支持[no](仅适用于Unix)
-slog2 .............启用slog2支持[自动](仅限QNX)
7.Network options:
-ssl .................启用SSL支持方法[自动]
-no-openssl ..........不要使用OpenSSL [Apple和WinRT上的默认]
-openssl-linked ......使用OpenSSL并链接到libssl [no]
-openssl-runtime .....使用OpenSSL并动态加载libssl [auto]
-securetransport .....使用SecureTransport [auto](仅限Apple)
-sctp ................启用SCTP支持[no]
-libproxy ............启用libproxy的使用[no]
-system-proxies ......默认使用系统网络代理[yes]
8.Gui, printing, widget options:
-cups ................启用CUPS支持[自动](仅适用于Unix)
-fontconfig ..........启用Fontconfig支持[auto](仅适用于Unix)
-freetype ............选择使用的FreeType [system / qt / no]
-harfbuzz ............选择用过的HarfBuzz-NG [系统/ qt / no](不在Apple和Windows上自动检测)
-gtk .................启用GTK平台主题支持[auto]
-lgmon ...............启用lgmon支持[自动](仅限QNX)
-no-opengl ...........禁用OpenGL支持
-opengl <api> ........启用OpenGL支持。支持的API:es2(在Windows上默认),桌面(在Unix上默认),动态(仅限Windows)
-opengles3 ...........启用OpenGL ES 3.x支持而不是ES 2.x [自动]
-angle ...............使用捆绑的ANGLE支持OpenGL ES 2.0 [自动](仅限Windows)
-combined-angle-lib ..将LibEGL和LibGLESv2合并到LibANGLE(仅限Windows)
-qpa <name> ..........选择默认的QPA后端(例如,xcb,cocoa,windows)
-xcb-xlib .............启用Xcb-Xlib支持[auto]
9.Platform backends:
-direct2d ..........启用Direct2D支持[自动](仅限Windows)
-directfb ..........启用DirectFB支持[no](仅适用于Unix)
-eglfs .............启用EGLFS支持[auto;没有在Android和Windows上]
-gbm ...............为GBM [auto]启用后端(仅限Linux)
-kms ...............启用KMS [auto]的后端(仅适用于Linux)
-linuxfb ...........启用Linux Framebuffer支持[auto](仅限Linux)
-mirclient .........启用Mir客户端支持[no](仅Linux)
-xcb ...............选择使用的xcb- *库[system / qt / no](-qt-xcb仍然使用libxcb本身的系统版本)
10.Input backends:
-evdev .............启用evdev支持[auto]
-imf ...............启用IMF支持[自动](仅限QNX)
-libinput ..........启用libinput支持[auto]
-mtdev .............启用mtdev支持[auto]
-tslib .............启用tslib支持[自动]
-xinput2 ...........启用XInput2支持[自动]
-xkbcommon-x11 .....选择与xcb结合使用的xkbcommon[系统/ QT / NO]
-xkb-config-root <dir> ...使用-qt-xkbcommon-x11,设置默认的XKB配置根目录<dir> [检测]
-xkbcommon-evdev ...启用X-less xkbcommon与libinput结合使用[汽车]
11.Image formats:
-gif ...............启用对GIF的读取支持[自动]
-ico ...............启用对ICO的支持[是]
-libpng ............选择用过的libpng [system / qt / no]
-libjpeg ...........选择使用的libjpeg [system / qt / no]
12.Database options:
-sql- <driver> ........启用SQL <驱动程序>插件。支持的驱动db2 ibase mysql oci odbc psql sqlite2 sqlite tds[全自动]
-sqlite ..............选择用过的sqlite3 [系统/ qt]
13.Qt3D options:
-assimp ..............选择使用的assimp库[system / qt / no]
-qt3d-profile-jobs ...启用作业分析[no]
-qt3d-profile-gl .....启用OpenGL分析[no]
-qt3d-simd ...........选择SIMD支持级别[no / sse2 / avx2]
-qt3d-render .........启用Qt3D渲染方面[是]
-qt3d-input ..........启用Qt3D输入方面[是]
-qt3d-logic ..........启用Qt3D逻辑方面[是]
-qt3d-extras .........启用Qt3D Extras方面[yes]
-qt3d-animation .......启用Qt3D动画方面[是]
14.Multimedia options:
-pulseaudio ..........启用PulseAudio支持[自动](仅适用于Unix)
-alsa ................启用ALSA支持[自动](仅适用于Unix)
-no-gstreamer ........禁用对GStreamer的支持
-gstreamer [版本]。启用GStreamer支持[自动]在没有参数的情况下,首先尝试1.0,然后再尝试0.10。
-mediaplayer-backend <名称> ...选择媒体播放器后端(仅限Windows)支持的后端:directshow(默认),wmf
15.Webengine options:
-webengine-alsa ................启用ALSA支持[自动](仅限Linux)
-webengine-pulseaudio ..........启用PulseAudio支持[自动](仅限Linux)
-webengine-embedded-build ......启用Linux嵌入式构建[auto](仅限Linux)
-webengine-icu .................使用系统ICU库[system / qt](仅限Linux)
-webengine -ffmpeg ..............使用系统FFmpeg库[system / qt](仅限Linux)
-webengine-opus ................使用系统Opus库[system / qt](仅限Linux)
-webengine-webp ................使用系统WebP库[system / qt](仅限Linux)
-webengine-pepper-plugins ......启用Pepper Flash和Widevine插件[自动]
-webengine-printing-and-pdf ....启用打印和输出到PDF[汽车]
-webengine-proprietary-codecs ..启用对专有编解码器的支持[no]
-webengine-spellchecker ........启用对拼写检查程序的支持[是]
-webengine-native-spellchecker。启用对原生拼写检查器的支持[否](仅限macOS)
-webengine-webrtc ..............启用对WebRTC的支持[自动]
————————————————
版权声明:本文为CSDN博主「天空之城8020」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/kongcheng253/article/details/129001104

13
qt/Qt乱码问题.txt Normal file
View File

@ -0,0 +1,13 @@
《在windows下解决乱码问题的一个比较完美的方法(纯UTF-8环境使用下)(不影响系统其他软件的使用)》
一、Qt设置文件编码为:
(1) UTF-8
(2) BOM 如果是UTF-8则添加
二、Qt项目中运行的时候使用外部Terminal(也就是CMD)且做如下设定:
(1) 先在启动的外部 cmd 窗口属性中勾选使用旧版控制台,然后重新启动一次(Qt运行项目的cmd,不是运行cmd)。
(2) 步骤一完成后在注册表(regedit)中的HKEY_CURRENT_USER\Console\下会有
一个 qt_creator_process_stub 的一个项,将此项中的 CodePage 名称的值更改为
十进制(65001)后保存。
(3) 此时重新运行Qt项目,发现还是有乱码,此时,将步骤一中的勾选取消就可以了。
《此方法未测试》
SetConsoleOutputCP(65001);