c++ 指针的安全问题
指针是一个强大的工具,但它们可能导致多种安全问题。接下来我们一起研究一下会出现的安全问题。欢迎大家补充说明!!!
悬挂指针(也称为悬空指针或迷途指针)
是指向一块已经释放或无效内存的指针。悬挂指针的出现通常是由于对象被删除或释放后,有指针仍然保留着指向该内存地址的引用,但此时该地址上的数据已经不再有效或被分配给其他用途。
下面是悬挂指针出现的典型场景及其危险性:
int* ptr = new int(10); // 动态分配一个整数
delete ptr; // 释放内存
// ptr 现在成为悬挂指针,因为它指向被释放的内存
delete操作之后,ptr仍然保存着之前分配的内存地址,但这块内存已经被归还给操作系统或用来存放其他内容,在这段内存上进行读写操作会导致不可预期的行为,包括数据损坏和程序崩溃。
悬挂指针的危险性
1、未定义的行为:对悬挂指针解引用或在其上进行操作可能导致未定义行为,这意味着程序可能会崩溃,或者更糟糕的是,静默地继续运行并产生错误数据。
2、安全漏洞:悬挂指针可能会被恶意利用,导致安全漏洞,如缓冲区溢出和其他类型的攻击。
如何避免悬挂指针
1、及时清空指针:释放内存后,立即将指针设置为nullptr,这样任何对指针的后续访问都将是对空指针的访问,这虽然不能解引用,但至少避免了悬挂指针的问题。
delete ptr;ptr = nullptr; // 避免悬挂指针
2、局部变量的生命周期:尽量使用局部变量(包括RAII对象和智能指针)来管理资源,这样当变量离开作用域时,资源就会自动释放。
3、智能指针的使用:使用C++的智能指针(如std::unique_ptr和std::shared_ptr),它们能够自动管理内存,确保对象的生命周期得到适当的控制。
4、避免原始指针:在不需要低级内存操作的情况下,尽量避免使用原始指针。
野指针(也称为悬空指针)
指向不可预测内存位置的指针。它通常是由于指针没有被初始化、已经释放或已经删除的内存的指针。
野指针的危险性在于,它可能指向任何地方,包括无效或者保留的内存区域。对野指针的解引用是非法的,它会导致未定义的行为,可能会引发程序崩溃或者更糟糕的后果。与悬挂指针类似,野指针也有可能被用于攻击,从而导致安全漏洞。
总之野指针问题通常源于不当的内存管理。在C++程序设计中,应该密切关注指针的使用,确保它们在任何时刻都指向有效的内存地址或者为nullptr。
野指针产生的情况
1、未被初始化的指针:
int* ptr; // 未初始化的指针
*ptr = 5; // 未定义行为,对野指针解引用
2、指针释放后遗忘置空:
int* ptr = new int(10); // 动态分配内存
delete ptr; // 释放内存
// 如果在此后没有将 ptr 置为 nullptr,它将变成野指针
避免野指针的策略:
1、始终初始化指针: 声明指针时,应该立即将其初始化为nullptr,或者给它一个有效的内存地址。
int* ptr = nullptr; // 安全地初始化为nullptr
2、分配内存后进行检查: 在使用动态内存分配(如 new 或 malloc)后,检查是否分配成功,并在内存分配失败时采取适当的错误处理。
3、释放内存后立即置空: 释放指针指向的内存后,立即将指针置为nullptr。
delete ptr;
ptr = nullptr; // 避免野指针
4、使用智能指针: 尽量使用标准库中的std::unique_ptr或std::shared_ptr等智能指针,它们会自动管理生命周期,从而避免野指针问题。
5、避免复杂的指针操作: 尽量简化使用指针的代码,避免不必要的指针操作,减少出错机率。
6、代码审查和静态分析: 使用代码审查和静态分析工具来检测潜在的野指针使用。
内存泄漏
内存泄漏指的是程序在运行过程中分配了内存(通过 new、malloc 等),但没有适时释放(使用 delete 或 free),导致已分配的内存既不被使用也无法被回收。这会导致程序的内存消耗持续增加,最终可能耗尽系统资源,影响程序的性能,甚至导致程序崩溃
示例
函数 createMemoryLeak 分配了一个整型数的内存,但并没有释放它。因此,当函数执行完毕后,分配的内存空间由于没有指针引用它,变得无法访问,导致内存泄漏。
#include <iostream>void createMemoryLeak() {int* leakyInt = new int(42); // 动态分配,没有相应的 delete
}int main() {createMemoryLeak(); // 调用会产生内存泄漏的函数// ... 程序其他代码return 0;// 程序结束后,由于缺乏 delete,分配的内存被泄漏
}
避免内存泄漏的方法
1、使用智能指针:C++11以后,推荐使用智能指针 (如 std::unique_ptr 和 std::shared_ptr) 来自动管理内存。智能指针在销毁时会自动释放它们所拥有的资源,有效防止内存泄漏。
#include <memory>void safeFunction() {auto safePtr = std::make_unique<int>(42); // 使用 unique_ptr,无需手动释放}
2、遵循 RAII 原则:资源获取即初始化(Resource Acquisition Is Initialization) 原则是现代 C++ 程序设计的基础。确保资源(如内存、文件句柄等)的获取和释放始终与对象的生命周期保持一致。
3、仔细管理裸指针:如果不得不使用裸指针,应确保每个 new 与一个 delete 相对应,每个 new[] 与一个 delete[] 相对应。
4、尽量使用标准库容器:例如 std::vector、std::string 等,它们管理内存的生命周期,减少了手动内存管理的需求。
5、代码审查和自动化测试:通过工具和测试来检测代码中的内存泄漏,写出更健壮的代码。
6、使用内存泄漏检测工具:使用像 Valgrind、AddressSanitizer,或者 Visual Studio 的内存检测工具来帮助发现和锁定内存泄漏的位置。
内存泄漏检测工具
Valgrind: 一个广泛使用的Linux下的内存检测工具,可以帮助发现内存泄漏以及其他内存相关错误。
AddressSanitizer(ASan): 一个快速的内存错误检测器,可以检测出包括内存泄漏在内的各种内存访问错误。
Visual Studio: 提供了内置的内存泄漏检测工具,在调试模式下运行程序时可以帮助发现内存泄漏。
缓冲区溢出
缓冲区溢出(buffer overflow)是一种安全漏洞,它发生在程序试图将数据写入一个固定长度的缓冲区,而写入的数据量超过了缓冲区可以容纳的大小。由于 C++ 不会自动检查数组边界,所以当进行数组操作时,如果不慎,很容易发生缓冲区溢出。
缓冲区溢出可能导致程序崩溃、数据损坏,甚至让攻击者有机会执行任意代码,这在某些情况下会导致安全漏洞。
缓冲区溢出示例
buffer 数组定义为长度 10,但在 for 循环中,我们写入了 11 个字符(从 0 到 10,包括两端),因此,当 i 为 10 时,我们会尝试写入数组的边界之外,这就会导致缓冲区溢出。
#include <iostream>void bufferOverflowExample() {char buffer[10];for(int i = 0; i <= 10; i++) {buffer[i] = 'a'; // i = 10 时会导致缓冲区溢出}
}int main() {bufferOverflowExample(); // 调用函数,演示缓冲区溢出return 0;
}
防止缓冲区溢出:
1、使用标准库容器: 例如 std::vector 和 std::string 来替代原始数组。这些容器会自动地管理内存,并提供边界检查操作。
2、边界检查: 如果必须使用原始数组,确保对所有的数组访问操作进行边界检查。
3、使用安全函数: 尽量使用安全的函数来代替旧的函数。比如使用 std::strncpy 代替 strcpy,使用 std::snprintf 代替 sprintf。
4、堆栈保护: 现代编译器通常提供选项以增加堆栈保护,可以帮助阻止缓冲区溢出攻击。
5、避免不安全的函数: 一些函数本身就存在安全隐患,比如 gets 函数,应当避免使用。
6、代码审查: 持续审查代码,查找可能的缓冲区溢出风险。
7、动态检测工具: 使用动态内存调试工具,如 Valgrind 或 AddressSanitizer,它们可以在开发过程中帮助发现缓冲区溢出。
8、静态代码分析: 许多现代 IDE 和静态代码分析工具可以扫描源代码,查找潜在的缓冲区溢出风险。
9、使用堆分配: 当分配大型数据结构时,使用堆 (通过 new 或 std::make_unique 等) 而非栈,以避免栈溢出。
10、开启编译器安全检查: 某些编译器提供编译时检查,可以帮助检测数组边界问题。
典型的编译器安全选项
GCC/Clang 有 -fstack-protector 选项开启堆栈保护。
Visual Studio 提供 /GS 以增加安全检查。
释放非动态分配的内存
尝试释放非动态分配的内存(即没有使用 new 或者 malloc 系列函数分配的内存)是一个严重的编程错误。这种错误会导致未定义行为(undefined behavior),这意味着程序可能会崩溃、损坏数据、运行异常或者有时看似正常运行,使得问题难以跟踪和调试。
非动态分配内存示例
指针 ptr 指向的是栈上分配的变量 i 的地址,而不是通过 new 关键字分配的堆内存。尝试用 delete 释放栈上的变量是不允许的,这会导致程序运行出现未定义行为。
int main() {int i = 42;int* ptr = &i;// 错误:试图释放一个非动态分配的指针delete ptr; // 未定义行为return 0;
}
正确的动态内存分配和释放
只有通过 new 分配的内存才应该用 delete 释放,通过 new[] 分配的内存应该用 delete[] 释放。类似地,malloc 分配的内存应该用 free 释放。
int main() {// 正确:使用 new 分配动态内存int* ptr = new int(42);// 使用指针做一些事情...// 正确:使用 delete 释放动态分配的内存delete ptr;return 0;
}
如何避免这种错误
1、使用智能指针:智能指针如 std::unique_ptr 或 std::shared_ptr 可以自动管理内存的释放,这样就不需要手动调用 delete。
2、尽量避免裸指针:如果可以,尽量使用栈分配或者标准库容器类,比如 std::vector 或 std::string,这样就不需要直接处理内存分配和释放。
3、代码审查和自动化测试:通过代码审查和测试可以帮助检测和防止这类错误。
4、清晰的所有权管理:在设计软件时,清晰地定义哪部分代码负责分配和释放内存。
5、使用 RAII (Resource Acquisition Is Initialization) 原则:封装资源管理在对象内,利用构造函数分配和析构函数释放资源,保证资源的正确管理。
6、编写自动化测试:通过自动化测试来检测内存管理的问题,确保在释放之前内存是通过正确的方式分配的。
前越界和后越界访问
在c++中,数组的前越界访问和后越界访问是两种常见的内存安全错误。它们都属于缓冲区溢出(buffer overflow)的范畴。
后越界访问
后越界访问发生在当你尝试访问一个数组或缓冲区结束之后的内存位置时。常见的情况是,访问数组时超出其已定义的长度范围。这种错误可能引起程序崩溃或行为异常,并且可以被恶意利用来攻击软件系统。
int arr[5] = {0, 1, 2, 3, 4};
// 越界访问:访问数组后面的元素
int value = arr[5]; // 错误,arr[5] 实际上是 arr 数组后的第一个位置
前越界访问
前越界访问发生在访问数组或缓冲区开始之前的内存位置时。这种情况不像后越界那么常见,但同样会导致未定义行为。
int arr[5] = {0, 1, 2, 3, 4};// 越界访问:访问数组前面的元素
int value = *(arr - 1); // 错误,arr - 1 指向数组前面的位置
如何避免越界访问
1、使用标准库容器:使用 std::vector, std::array, std::string 等 STL 容器,它们提供了边界检查的方法(如 at() 成员函数),如果越界,它们会抛出异常。
2、边界检查:总是在数组操作之前执行边界检查,确保索引是有效的。
3、使用迭代器和范围基 for 循环:尽量使用迭代器或者范围基 for 循环进行数组或容器的遍历,这样可以避免直接操作索引。
4、静态和动态分析工具:利用静态分析工具(诸如 Clang Static Analyzer 或者 cppcheck)和动态分析工具(比如 Valgrind 或者 AddressSanitizer)检测代码中可能存在的越界访问。
5、自动化测试和代码审查:编写测试用例以捕获边界条件,并进行代码审查以确保遍历操作的正确性。
6、避免裸指针操作:尽量减少指针算术操作,如果不得不使用,确保操作是安全的。
7、初始化和清零:对于本地数组,可在声明时对它们进行初始化或清零,以避免不小心使用未初始化的内存。
注意:
C++ 标准库容器的 operator[] 方法通常不会做边界检查,而是假设你已经知道你在做什么。这使得这个操作更加高效,但也更危险。如果你需要边界检查,请使用容器的 at() 方法,它会在越界时抛出 std::out_of_range 异常。
异常和错误处理不当
在 C++ 编程中,异常和错误处理是关键的程序设计考量。不当的异常和错误处理可能会导致资源泄露、程序崩溃、不一致的状态和安全漏洞。以下是一些常见的异常和错误处理不当的情况和如何避免它们。
1. 不捕获可能抛出异常的代码
当你的代码调用可能抛出异常的函数或方法,而却没有捕获异常,可能会导致程序的非正常终止。
解决方法:使用 try-catch 块包围可能抛出异常的代码,并根据可能发生的错误类型来处理异常。
2. 过宽泛的异常捕获
使用过宽泛的异常捕获(如捕获所有类型的异常)可能会掩盖问题的真正原因,并导致调试困难。
解决方法:尽量捕获特定的异常类型,这有利于更精确地处理错误并提供更有用的调试信息。
3. 异常处理中忽略资源释放
在异常处理过程中,如果没能正确释放资源(如动态分配的内存、文件句柄、锁等),将会导致资源泄露。
解决方法:利用 RAII(Resource Acquisition Is Initialization)原则管理资源,使用智能指针如 std::unique_ptr 和 std::shared_ptr 管理动态分配的内存,使用 std::lock_guard 和 std::unique_lock 管理锁,确保在栈展开(stack unwinding)时资源可以被自动释放。
4. 安静捕获和吞噬异常
在 catch 块中什么都不做(或者只打印错误消息)然后继续执行,有可能导致程序在一个不确定的状态下继续运行。
解决方法:在 catch 块中恰当地处理异常。如果不能处理,应该再次抛出或终止程序。
5. 在构造函数和析构函数中抛出异常
如果构造函数抛出异常,在没有完全构建该对象的情况下,析构函数不会被调用,可能会导致资源泄露。此外,在析构函数中抛出异常,如果同时有其它异常抛出,可能会导致 std::terminate 被调用。
解决方法:保证构造函数中的代码能够安全地处理异常,不要在析构函数中抛出异常。
6. 检查错误代码
一些 C++ 的库和接口使用返回值来表示成功或错误。忽略这些返回值可能会导致错误未被检测到。
解决方法:总是检查函数返回的错误代码,并根据错误代码进行相应的处理。
7. 使用异常作为普通流程控制
异常应该仅用于异常情况,它们不应该被用作执行普通流程控制,因为这样会降低程序性能,并且会让程序逻辑更难以理解。
解决方法:只针对确实异常的情况抛出和处理异常,使用其他方式(如条件判断)来处理正常逻辑。
8. 内存不足异常 std::bad_alloc
在使用动态内存分配时,例如 new 操作符可能会抛出 std::bad_alloc。不处理这种异常可能会导致程序崩溃。
解决方法:对可能抛出 std::bad_alloc 的代码使用 try-catch 块并适当处理,或者使用 noexcept 的 new (std::nothrow) 形式。
9. 错误的异常规格说明(Exception Specification)
C++11 之前,异常规格说明(如 throw(Type))用于表明函数可能抛出的异常类型。在 C++11 后,这个语法被 noexcept 取代。
解决方法:尽量避免使用异常规格说明,转而使用 noexcept 关键字,这能提供更明确的异常安全保证。
10. 递归异常
在 catch 代码块中抛出一个新的异常,而没有释放捕获的异常,将导致异常递归,可能消耗过多资源甚至栈溢出。
解决方法:避免在 catch 块内抛出新的异常,如果必要,应该在之前将异常释放或转换为适当的类型。
通过积极地关注异常和错误处理,可以提高程序的可靠性、可维护性,并且减少潜在的安全风险。
相关文章:
c++ 指针的安全问题
指针是一个强大的工具,但它们可能导致多种安全问题。接下来我们一起研究一下会出现的安全问题。欢迎大家补充说明!!! 悬挂指针(也称为悬空指针或迷途指针) 是指向一块已经释放或无效内存的指针。悬挂指针…...

高质量训练数据助力大语言模型摆脱数据困境 | 景联文科技
目前,大语言模型的发展已经取得了显著的成果,如OpenAI的GPT系列模型、谷歌的BERT模型、百度的文心一言模型等。这些模型在文本生成、问答系统、对话生成、情感分析、摘要生成等方面都表现出了强大的能力,为自然语言处理领域带来了新的突破。 …...
elasticsearch查询
(1)简单查询 curl -XGET http://127.0.0.1:9201/_search curl -XGET http://127.0.0.1:9201/test231208/_search curl -XGET http://127.0.0.1:9201/test231208/_doc/_search curl -XGET http://127.0.0.1:9201/test231208/_doc/id (2&…...

Vue + JS + tauri 开发一个简单的PC端桌面应用程序
Vue JS tauri 开发一个简单的PC端桌面应用程序 文章目录 Vue JS tauri 开发一个简单的PC端桌面应用程序1. 环境准备1.1 安装 Microsoft Visual Studio C 生成工具[^2]1.2 安装 Rust[^3] 2. 使用 vite 打包工具创建一个 vue 应用2.1 使用Vite创建前端Vue项目2.2 更改Vite打包…...

7.5 MySQL对数据的增改删操作(❤❤❤)
7.5 MySQL对数据的基本操作 1. 提要2. 数据添加2.1 insert语法2.2 insert 子查询2.3 ignore关键字 3. 数据修改3.1 update语句3.2 update表连接 4. 数据删除4.1 delete语句4.2 delete表连接4.3 快速删除数据表全部数据 1. 提要 2. 数据添加 2.1 insert语法 2.2 insert 子查询 …...

kibana查看和展示es数据
本文来说下使用kibana查看和展示es数据 文章目录 数据准备查询所有文档示例kibana查看和展示es数据 数据准备 可以使用es的命令或者java程序来往,es进行新增数据 查询所有文档示例 在 apifox 中,向 ES 服务器发 GET请求 :http://localhost:92…...

若依修改侧边栏
引用:https://blog.csdn.net/Sabrina_cc/article/details/125871591 子菜单选中后,文字和背景改变: .el-submenu__title i{color: #e8e8e8 !important;} #app .sidebar-container .theme-dark .nest-menu .el-submenu .is-active > .el-su…...
Linux篇之Centos中将系统时间设置为本地时间
要在 CentOS 上将系统时间设置为本地时间,可以按照以下步骤进行操作: 1.首先,你需要确定你想要设置的本地时间。例如,如果你想要将系统时间设置为当前时间(假设是北京时间),则可以使用以下命令获…...

翼龙-2H无人机
一、概述 翼龙-2,是成都飞机工业集团研制的无人驾驶飞行器,是空中侦察、精确打击和应急通讯的平台。成都飞机工业集团于2015年9月的北京国际航空航天展览会上介绍了翼龙-2的概念。在2016年珠海航展期间,翼龙-2的原型机首次向公众展示。 因为…...

解析Transformer模型
原文地址:https://zhanghan.xyz/posts/17281/ 进入Transformer RNN很难处理冗长的文本序列,且很容易受到所谓梯度消失/爆炸的问题。RNN是按顺序处理单词的,所以很难并行化。 用一句话总结Transformer:当一个扩展性极佳的模型和一…...

【深度学习】RTX2060 2080如何安装CUDA,如何使用onnx runtime
文章目录 如何在Python环境下配置RTX 2060与CUDA 101. 安装最新的NVIDIA显卡驱动2. 使用conda安装CUDA Toolkit3. 验证onnxruntime与CUDA版本4. 验证ONNX需求版本5. 安装ONNX与onnxruntime6. 编写ONNX推理代码 如何在Python环境下配置RTX 2060与CUDA 10 RTX 2060虽然是一款较早…...

力扣刷MySQL-第二弹(详细解析)
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:力扣刷题讲解-MySQL 🍹文章作者技术和水平很有限,如果文中出…...

LiveGBS流媒体平台GB/T28181功能-基础配置接入控制白名单黑名单配置控制设备安全接入设备单独配置接入密码
LiveGBS基础配置接入控制白名单黑名单配置控制设备安全接入设备单独配置接入密码 1、白名单配置应用场景2、接入控制2.1、白名单2.2、黑名单 3、搭建GB28181视频直播平台 1、白名单配置应用场景 LiveGBS国标流媒体服务,支持白名单配置。 可在设备注册前࿰…...

企业网站建站源码系统:Thinkphp5内核企业网站建站模板源码 带完整的安装代码包以及搭建教程
随着互联网的快速发展,企业对于网站的需求日益增强。为了满足这一市场需求,小编给大家分享一款基于Thinkphp5内核的企业网站建站源码系统。该系统旨在为企业提供一套功能强大、易于使用的网站建设解决方案,帮助企业快速搭建自己的官方网站&am…...

SC20-EVB ubuntu14.04 Andriod 5.1 SDK编译下载
1.ubuntu14.04安装环境配置 vi /etc/profile to add export JAVA_HOME/usr/lib/jvm/java-7-openjdk-amd64 export JRE_HOME J A V A H O M E / j r e e x p o r t C L A S S P A T H . : {JAVA_HOME}/jre export CLASSPATH.: JAVAHOME/jreexportCLASSPATH.:{JAVA_HOME}/lib…...

OpenCV——图像按位运算
目录 一、算法概述1、逻辑运算2、函数解析3、用途 二、代码实现三、结果展示 OpenCV——图像按位运算由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法概述 1、逻辑运算 OpenCV4 针对两个图像之…...

5 个被低估的开源项目
文章目录 1.集算器 -数据处理2. Firecamp - 邮递员替代方案3.Keploy——后端 测试4. Hanko - 密钥验证5. Zrok - Ngrok 类固醇 长话短说 本文列出了五个不太受欢迎的优秀项目,您应该尝试一下。🔥 这些工具旨在改进数据处理、API 开发、后端测试、身份验…...

go语言初探(一)
package mainimport ("fmt""time" )func main() {fmt.Print("hello go!")time.Sleep(1 * time.Second)}运行后,结果如下: 1、golang表达式中,加;和不加;都可以 2、函数的{和函数名一…...

跟着cherno手搓游戏引擎【7】Input轮询
在引擎程序中任何时间,任何位置都能知道按键是否按下、鼠标的位置等等信息。 与事件系统的区别:事件系统是在按下时调用并传递按键状态;轮询是每时每刻都能获取按键状态 创建基类: YOTO/Input.h:名如其意 #pragma …...
stm32 - GPIO高级用法
stm32 - GPIO高级用法 PWMPWM / LEDPWM / 电机 PWM PWM / LED PWM波通过改变占空比可以改变LED的亮度 PWM信号调节LED亮度时,信号频率保持不变,即一个周期时间不变,改变的是脉冲的高电平的时间,即LED的导通时间,占空比…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...