当前位置: 首页 > news >正文

FFmpeg中内存分配和释放相关的源码:av_malloc函数、av_mallocz函数、av_free函数和av_freep函数分析

一、av_malloc函数分析

(一)av_malloc函数的声明

av_malloc函数的声明放在在FFmpeg源码(本文演示用的FFmpeg源码版本为5.0.3,该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译)的头文件libavutil/mem.h中:

/*** Allocate a memory block with alignment suitable for all memory accesses* (including vectors if available on the CPU).** @param size Size in bytes for the memory block to be allocated* @return Pointer to the allocated block, or `NULL` if the block cannot*         be allocated* @see av_mallocz()*/
void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1);

根据注释,可以了解到该函数作用是分配一个适合所有内存访问的内存块(包括动态数组,如果CPU上可用)。形参size:要分配的内存块的字节大小。返回值:指向分配块的指针;如果无法申请内存,则返回NULL。

宏定义av_malloc_attrib也被定义在libavutil/mem.h中:

/*** @def av_malloc_attrib* Function attribute denoting a malloc-like function.** @see <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bmalloc_007d-function-attribute-3251">Function attribute `malloc` in GCC's documentation</a>*/#if AV_GCC_VERSION_AT_LEAST(3,1)#define av_malloc_attrib __attribute__((__malloc__))
#else#define av_malloc_attrib
#endif

这里用attribute指定__malloc__属性,表示这样标记的函数(av_malloc函数)返回的块不得包含任何指向其他对象的指针。这样做的目的是帮助编译器估计哪些指针可能指向同一个对象:该属性告诉GCC,它不必担心函数返回的对象可能包含指向它正在跟踪的其他对象的指针。具体可以参考:GCC: __attribute__((malloc))

宏定义av_malloc_attrib也被定义在libavutil/mem.h中:

/*** @def av_alloc_size(...)* Function attribute used on a function that allocates memory, whose size is* given by the specified parameter(s).** @code{.c}* void *av_malloc(size_t size) av_alloc_size(1);* void *av_calloc(size_t nmemb, size_t size) av_alloc_size(1, 2);* @endcode** @param ... One or two parameter indexes, separated by a comma** @see <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007balloc_005fsize_007d-function-attribute-3220">Function attribute `alloc_size` in GCC's documentation</a>*/#if AV_GCC_VERSION_AT_LEAST(4,3)#define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
#else#define av_alloc_size(...)
#endif

这里用attribute指定alloc_size属性,用于告诉编译器函数返回值指向的内存,其大小是由alloc_size中的参数指定,主要用于提高__builtin_object_size的正确性。具体参考:GCC __atrribute__

然后宏定义用到了变参__VA_ARGS__,可以参考:C 语言 define 变参__VA_ARGS__使用

所以函数声明void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1) 等价于:

void *av_malloc(size_t size) __attribute__((__malloc__)) __attribute__((alloc_size(1)))

简单来讲,__attribute__只是让代码优化得更好而已,我们可以忽略。

(二)av_malloc函数的实现原理

av_malloc函数定义在libavutil/mem.c中:

#define HAVE_POSIX_MEMALIGN 1
#define HAVE_ALIGNED_MALLOC 0
#define HAVE_MEMALIGN 1
#define HAVE_AVX512 0
#define HAVE_AVX 0
#define CONFIG_MEMORY_POISONING 0
#define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16))static atomic_size_t max_alloc_size = ATOMIC_VAR_INIT(INT_MAX);void *av_malloc(size_t size)
{void *ptr = NULL;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = memalign(size, ALIGN);
#endif/* Why 64?* Indeed, we should align it:*   on  4 for 386*   on 16 for 486*   on 32 for 586, PPro - K6-III*   on 64 for K7 (maybe for P3 too).* Because L1 and L2 caches are aligned on those values.* But I don't want to code such logic here!*//* Why 32?* For AVX ASM. SSE / NEON needs only 16.* Why not larger? Because I did not see a difference in benchmarks ...*//* benchmarks with P3* memalign(64) + 1          3071, 3051, 3032* memalign(64) + 2          3051, 3032, 3041* memalign(64) + 4          2911, 2896, 2915* memalign(64) + 8          2545, 2554, 2550* memalign(64) + 16         2543, 2572, 2563* memalign(64) + 32         2546, 2545, 2571* memalign(64) + 64         2570, 2533, 2558** BTW, malloc seems to do 8-byte alignment by default here.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}

去掉一大堆其它东西,av_malloc函数的核心实现就是:

void *av_malloc(size_t size)
{//...void *ptr = NULL;if (posix_memalign(&ptr, ALIGN, size)){ptr = NULL;}//...return ptr;}	

可以看到其本质就是调用了posix_memalign函数,该函数是Linux下内存对齐的函数,其作用是分配size大小的字节,并将分配的内存地址存放在ptr中。分配的内存的地址将是ALIGN的倍数,且必须是2的幂次方和sizeof(void*)的倍数。如果size为0,则函数返回NULL或一个唯一的指针值,以便可以成功传递给free函数。如果分配成功返回0该函数跟malloc函数相近。mallocposix_memalign函数跟mallocmalloc函数的区别是: malloc函数总是返回8字节对齐的内存地址,在64bits上是16字节对齐;而对于更大的边界,例如页面,需要动态的对齐的时候就可以选择posix_memalign函数。具体可以参考:posix_memalign(3) — Linux manual page

总结:av_malloc函数作用是分配一个适合所有内存访问的内存块,形参size为 要分配的内存块的字节大小。其底层实现就是调用了posix_memalign函数。

二、av_mallocz函数分析

(一)av_mallocz函数的声明

av_mallocz函数的声明放在在FFmpeg源码的头文件libavutil/mem.h中:

/*** Allocate a memory block with alignment suitable for all memory accesses* (including vectors if available on the CPU) and zero all the bytes of the* block.** @param size Size in bytes for the memory block to be allocated* @return Pointer to the allocated block, or `NULL` if it cannot be allocated* @see av_malloc()*/
void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1);

根据注释,可以了解到该函数作用是分配一个适合所有内存访问的内存块
(包括CPU上可用的动态数组)并将块的所有字节归零。形参size:要分配的内存块的字节大小。
返回值指向已分配块的指针,如果不能分配,则为NULL。

(二)av_mallocz函数的实现原理

av_mallocz函数定义在libavutil/mem.c中:

void *av_mallocz(size_t size)
{void *ptr = av_malloc(size);if (ptr)memset(ptr, 0, size);return ptr;
}

可以看到其核心就是调用了av_malloc函数分配内存块,随后调用memset函数将该内存块的所有字节清零。因为av_mallocz函数会将内存块清零(相当于对内存块进行一个初始化操作)。所以在FFmpeg源码中一般使用av_mallocz,而不会直接使用av_malloc函数。

三、av_free函数分析

(一)av_free函数的声明

av_free函数的声明放在在FFmpeg源码的头文件libavutil/mem.h中:

/*** Free a memory block which has been allocated with a function of av_malloc()* or av_realloc() family.** @param ptr Pointer to the memory block which should be freed.** @note `ptr = NULL` is explicitly allowed.* @note It is recommended that you use av_freep() instead, to prevent leaving*       behind dangling pointers.* @see av_freep()*/
void av_free(void *ptr);

根据注释,可以了解到该函数作用是释放av_malloc()/av_mallocz()函数分配的内存块。形参ptr:指向应该释放的内存块的指针。
 

(二)av_free函数的实现原理

av_free函数定义在libavutil/mem.c中:

void av_free(void *ptr)
{
#if HAVE_ALIGNED_MALLOC_aligned_free(ptr);
#elsefree(ptr);
#endif
}

可以看到其核心就是调用free函数释放空间。

四、av_freep函数分析

(一)av_freep函数的声明

av_freep函数的声明放在在FFmpeg源码的头文件libavutil/mem.h中:

/*** Free a memory block which has been allocated with a function of av_malloc()* or av_realloc() family, and set the pointer pointing to it to `NULL`.** @code{.c}* uint8_t *buf = av_malloc(16);* av_free(buf);* // buf now contains a dangling pointer to freed memory, and accidental* // dereference of buf will result in a use-after-free, which may be a* // security risk.** uint8_t *buf = av_malloc(16);* av_freep(&buf);* // buf is now NULL, and accidental dereference will only result in a* // NULL-pointer dereference.* @endcode** @param ptr Pointer to the pointer to the memory block which should be freed* @note `*ptr = NULL` is safe and leads to no action.* @see av_free()*/
void av_freep(void *ptr);

根据注释,可以了解到该函数作用是释放av_malloc()/av_mallocz()函数分配的内存块,并设置指向它的指针为NULL 。

(二)av_freep函数的实现原理

av_freep函数定义在libavutil/mem.c中:

void av_freep(void *arg)
{void *val;memcpy(&val, arg, sizeof(val));memcpy(arg, &(void *){ NULL }, sizeof(val));av_free(val);
}

可以看到其核心就是调用了av_free函数释放空间。然后av_freep函数可以避免仅使用av_free函数释放空间后出现的悬挂指针,避免安全风险。所以av_freep函数比仅使用av_free函数更安全。

五、编写测试例子,来理解av_mallocz函数和av_freep函数的使用

通过上述的讲解,相信大家已经了解了FFmpeg源码中这几个内存相关的函数,也理解了FFmpeg 源码中C语言的设计艺术。就拿FFmpeg的内存相关的函数来讲,其设计艺术在于:av_mallocz函数申请、分配内存后,还会对该内存块进行初始化清零的操作;av_freep函数在释放内存块空间后会把指针指向NULL。我们可以把av_mallocz函数和av_freep函数从FFmpeg源码中抽取出来,移植到我们自己的C语言代码中使用。这样在不依赖FFmpeg库文件的情况下,我们也能使用FFmpeg里面的函数。这就是最简单的对FFmpeg裁剪。

编写测试例子main.c,在CentOS 7.5上通过10.2.1版本的gcc可以成功编译 :

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdatomic.h>
#include <limits.h>#define HAVE_POSIX_MEMALIGN 1
#define HAVE_ALIGNED_MALLOC 0
#define HAVE_MEMALIGN 1
#define HAVE_AVX512 0
#define HAVE_AVX 0
#define CONFIG_MEMORY_POISONING 0
#define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16))static atomic_size_t max_alloc_size = ATOMIC_VAR_INIT(INT_MAX);#ifdef __GNUC__
#    define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
#    define AV_GCC_VERSION_AT_MOST(x,y)  (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
#else
#    define AV_GCC_VERSION_AT_LEAST(x,y) 0
#    define AV_GCC_VERSION_AT_MOST(x,y)  0
#endif#if AV_GCC_VERSION_AT_LEAST(3,1)#define av_malloc_attrib __attribute__((__malloc__))
#else#define av_malloc_attrib
#endif#if AV_GCC_VERSION_AT_LEAST(4,3)#define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
#else#define av_alloc_size(...)
#endifvoid *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1);
void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1);
void av_free(void *ptr);
void av_freep(void *ptr);void *av_malloc(size_t size)
{void *ptr = NULL;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = memalign(size, ALIGN);
#endif/* Why 64?* Indeed, we should align it:*   on  4 for 386*   on 16 for 486*   on 32 for 586, PPro - K6-III*   on 64 for K7 (maybe for P3 too).* Because L1 and L2 caches are aligned on those values.* But I don't want to code such logic here!*//* Why 32?* For AVX ASM. SSE / NEON needs only 16.* Why not larger? Because I did not see a difference in benchmarks ...*//* benchmarks with P3* memalign(64) + 1          3071, 3051, 3032* memalign(64) + 2          3051, 3032, 3041* memalign(64) + 4          2911, 2896, 2915* memalign(64) + 8          2545, 2554, 2550* memalign(64) + 16         2543, 2572, 2563* memalign(64) + 32         2546, 2545, 2571* memalign(64) + 64         2570, 2533, 2558** BTW, malloc seems to do 8-byte alignment by default here.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}void *av_mallocz(size_t size)
{void *ptr = av_malloc(size);if (ptr)memset(ptr, 0, size);return ptr;
}void av_free(void *ptr)
{
#if HAVE_ALIGNED_MALLOC_aligned_free(ptr);
#elsefree(ptr);
#endif
}void av_freep(void *arg)
{void *val;memcpy(&val, arg, sizeof(val));memcpy(arg, &(void *){ NULL }, sizeof(val));av_free(val);
}int main()
{uint8_t *pBuf = av_mallocz(128);if(pBuf){strcpy(pBuf, "hello world");printf("%s\n", pBuf);av_freep(&pBuf);if(!pBuf){printf("pBuf is free\n");}}return 0;
}

使用gcc编译,运行,输出如下:

六、参考文章

《FFmpeg5.0源码阅读——内存分配和释放》

相关文章:

FFmpeg中内存分配和释放相关的源码:av_malloc函数、av_mallocz函数、av_free函数和av_freep函数分析

一、av_malloc函数分析 &#xff08;一&#xff09;av_malloc函数的声明 av_malloc函数的声明放在在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为5.0.3&#xff0c;该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译&#xff09;的头文件libavutil/mem.h中&#xff1a;…...

七天进阶elasticsearch[Four]

依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>...

数据库-数据定义和操纵-DDL语言的使用

创建一个数据库&#xff1a; create database 数据库名; 选择数据库&#xff1a; use 数据库名; 创建表 create table 表名( ); 添加字段&#xff1b; ALTER TABLE 表名 ADD 新字段名 数据类型 [约束条件] [FIRST|AFTER 已存在字段名] ; 删除字段&#xff1a; ALTER TABLE 表…...

黄金价格与美元的关系变了?

在一些传统的定价框架中&#xff0c;现货黄金的价格走势取&#xff0c;决于美元的实际利率水平——实际利率越高&#xff0c;黄金价格越低&#xff0c;反之亦然。在大多数的时候&#xff0c;美元的实际利率决定了美元指数的高低所以人们通常认为&#xff0c;现货金价与美元呈反…...

VB.net与C# 调用InitializeComponent的区别

VB.NET与C# 调用InitializeComponent的区别 在VB.NET和C#中&#xff0c;InitializeComponent 方法的调用方式有所不同。 C#: 在C#中&#xff0c;InitializeComponent 方法通常是在构造函数中显式调用的。它用于初始化窗体和控件的属性。代码示例如下&#xff1a; public pa…...

【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 ​ 目录 一、问题描述 二、解题思路 方法一&#xff1a;数学公式推导法 方法…...

独立游戏之路:Tap篇 -- Unity 集成 TapTap 广告详细步骤

Unity 集成 TapADN 广告详细步骤 前言一、TapTap 广告介绍二、集成 TapTap 广告的步骤2.1 进入广告后台2.2 创建广告计划2.3 选择广告类型三、代码集成3.1 下载SDK3.2 工程配置3.3 源码分享四、常见问题4.1 有展现量没有预估收益 /eCPM 波动大?4.2 新建正式媒体找不到预约游戏…...

设计灵感源泉!7个令人赞叹的网页界面设计展示

网页的界面设计主要是指视觉设计和风格设计。高质量的界面更容易吸引用户的注意力&#xff0c;从而更准确地向用户传达信息。对于设计师来说&#xff0c;他们需要从高质量的作品中获得稳定的灵感&#xff0c;以帮助他们更高效地实现设计目标。在本文中&#xff0c;梳理了7个高质…...

vivado PIN

描述 引脚是基元或层次单元上的逻辑连接点。引脚允许 要抽象掉单元格的内容&#xff0c;并简化逻辑以便于使用。引脚可以 是标量的&#xff0c;包含单个连接&#xff0c;或者可以定义为对多个进行分组的总线引脚 信号在一起。 相关对象 引脚连接到一个单元&#xff0c;并且可以…...

docker部署mysql+nginx+redis

部署mysql 1、拉去镜像 docker search mysql docker pull mysql:5.7 2、运行镜像 docker run -p 3306:3306 --name mysql \ -v /home/mysql/log:/var/log/mysql \ -v /home/mysql/data:/var/lib/mysql \ -v /home/mysql/conf:/etc/mysql/conf.d \ -v /home/mysql/mysql-files…...

python文件操作、文件操作、读写文件、写模式

with读取文件数据内容 with open(filepath,mode,encoding) as file:#具体操作,例如&#xff1a;print(file.read())#查看文件所有的内容。 with&#xff1a;Python中的一个上下文管理器&#xff0c;用于简化资源的管理和释放。它可以用于任意需要进行资源分配和释放的情境…...

【亲测可用】docker进入正在运行的容器

微信公众号&#xff1a;leetcode_algos_life&#xff0c;代码随想随记 小红书&#xff1a;412408155 CSDN&#xff1a;https://blog.csdn.net/woai8339?typeblog &#xff0c;代码随想随记 GitHub: https://github.com/riverind 抖音【暂未开始&#xff0c;计划开始】&#xf…...

线程池吞掉异常的case:源码阅读与解决方法

1. 问题背景 有一天给同事CR&#xff0c;看到一段这样的代码 try {for (param : params) {//并发处理&#xff0c;func无返回值ThreadPool.submit(func(param));} } catch (Exception e) {log.info("func抛异常啦,参数是:{}", param) } 我&#xff1a;你这段代码是…...

基于mysqlbinlog恢复数据

1、把binlog转换为SQL mysqlbinlog --base64-outputdecode-rows -vv /usr/local/mysql/log-bin/mysql-bin.000003 >result.sql find / -name result.sql 2、查看events show binlog events in mysql-bin.000003; 3、回滚到3667那一行的数据 mysqlbinlog -v /usr/local/mys…...

Android_Android Studio 常用快捷键 for mac

功能快捷键运行ctrl R优化importctrl opt O格式化opt cmd L自动修正opt enter自动补齐cmd J自动生成代码cmd N搜索使用到的地方fn opt F7 ( cmd)搜索使用到的地方2shift cmd F搜索类cmd O当前文件搜索cmd F全局搜索按两下 shift搜索文件shift cmd O搜索符号opt…...

[EFI]NUC11电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板 英特尔 NUC11DBBi9&#xff08;LPC Controller WM590芯片组&#xff09; 处理器 11th Gen Intel Core i9-11900KB 3.30GHz 八核 已驱动内存32 GB ( 三星 DDR4 3200MHz 16GB x 2 )已驱动硬盘三星 MZVL21T0HCLR-00B00 (1024 GB / 固态硬盘)已驱动显卡AMD R…...

在Ubuntu上配置和设置防火墙UFW

在本文我们学习如何在Ubuntu上配置和设置UFW&#xff08;防火墙&#xff09;&#xff0c;UFW代表“不复杂的防火墙”&#xff0c;它充当IPTABLES的接口&#xff0c;从而简化了防火墙的配置过程&#xff0c;对于防火墙来说&#xff0c;这是非常困难的。初学者学习和配置防火墙规…...

nginx安装环境部署(完整步骤)

在部署nginx前&#xff0c;我们需要进行环境的部署 1.编译工具gcc&#xff0c;g,autoconf&#xff0c;automake &#xff0c;make sudo apt-get install gcc g autoconf automake make 2.依赖库zlib&#xff0c;openssl&#xff0c;pcre 2.1 openssl下载地址 https://www.open…...

如何做电子骑缝章?

制作电子骑缝章的过程可以依据不同情况和所使用的工具而有所不同&#xff0c;但基本思路是确保印章能够跨过页面接缝&#xff0c;以验证文档的完整性。以下是几种常见的方法&#xff1a; 使用专业电子合同平台 选择平台&#xff1a;首先&#xff0c;确保你使用的电子合同平台…...

2024.6.13 bailuo-Docker 安装与镜像拉取

2024.6.13 bailuo-Docker 安装与镜像拉取 2024.6.12 bailuo-安装与镜像拉取 卸载 Docker 如果已安装旧版 Docker 则先卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-en…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...