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

内存泄漏的影响

(1)内存泄漏是什么?

内存泄漏是指程序运行过程中分配的内存没有被正确释放,导致这部分内存无法再次使用,从而造成内存资源的浪费。内存泄漏可能会导致系统性能下降、程序崩溃或者消耗过多的系统资源;内存泄漏通常发生在动态分配的堆内存上,当程序通过调用malloc、new等函数来申请内存空间时,在使用完毕后应该使用free、delete等函数来释放这些已经不再需要的空间。如果忘记了释放这些空间,就会造成内存泄漏。

常见的引起内存泄漏的原因包括:指针或引用未被正确清理、循环引用、缓冲区溢出等。解决内存泄漏问题需要仔细检查代码,并确保所有分配的内存都得到了适时释放,对于大型项目和长时间运行的程序,及时发现和解决潜在的内存泄漏问题非常重要。可以利用工具进行静态代码分析或者动态检测来帮助定位和修复内存泄漏问题。同时,良好的编码习惯和使用智能指针等技术也有助于预防和减少内存泄漏的发生。

(2)内存占用过大为什么?

内存占用过大的原因可能有很多,以下是一些常见的情况:

  • 内存泄漏:当程序在运行时动态分配了内存但未正确释放时,会导致内存泄漏。这意味着那部分内存将无法再被其他代码使用,最终导致内存占用增加。

  • 频繁的动态内存分配和释放:如果程序中频繁进行大量的动态内存分配和释放操作,可能会导致内存碎片化问题。这样系统将难以有效地管理可用的物理内存空间。

  • 数据结构和算法选择不当:某些数据结构或算法可能对特定场景具有较高的空间复杂度,从而导致内存占用过大。在设计和选择数据结构和算法时应综合考虑时间效率和空间效率。

  • 缓存未及时清理:如果程序中使用了缓存机制,并且没有及时清理或管理缓存大小,就会导致缓存占用过多的内存空间。

  • 高并发环境下资源竞争:在高并发环境下,多个线程同时访问共享资源(包括对内存的申请和释放)可能引发资源竞争问题。若没有适当的同步机制或锁策略,可能导致内存占用过大。

  • 第三方库或框架问题:使用的第三方库或框架可能存在内存管理不当、内存泄漏等问题,从而导致整体程序的内存占用过大。

(3)内存泄露和内存占用过大区别?

内存泄漏指的是在程序运行过程中,动态分配的内存空间没有被正确释放,导致这些内存无法再被其他代码使用。每次发生内存泄漏时,系统可用的物理内存空间就会减少一部分,最终导致整体的内存占用量增加。

而内存占用过大则是指程序在运行时所消耗的物理内存超出了合理范围或预期值。除了因为内存泄漏导致的额外占用外,其他原因如频繁的动态内存分配和释放、数据结构和算法选择不当、缓存管理问题等都可能导致程序的内存占用过大。

可以说,内存在被正确管理和使用时,即使有一定程度的动态分配和释放操作,也不会造成明显的长期累积效应,即不会出现持续性的内存占用过大情况。而如果存在未及时释放或回收的资源(即发生了内存泄漏),随着时间推移会逐渐积累并导致整体的内存占用越来越高。

因此,在排查和解决内存占用过大问题时,需要注意是否存在内存泄漏,并且还需综合考虑其他可能导致内存占用过大的因素。

一、概述

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

特点

  • 隐蔽性 因为内存泄漏的产生原因是内存块未被释放,属于遗漏型缺陷而不是过错型缺陷

  • 积累性 内存泄漏通常不会直接产生可观察的错误症状,而是逐渐积累,降低系统整体性能,极端的情况下可能使系统崩溃。最直观的问题就是为什么我们的程序开始运行好好的,过段时间就异常退出。

内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于使用错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存未释放而浪费掉。

产生的原因

我们在进行程序开发的过程使用动态存储变量时,不可避免地面对内存管理的问题。程序中动态分配的存储空间,在程序执行完毕后需要进行释放。没有释放动态分配的存储空间而造成内存泄漏,是使用动态存储变量的主要问题。

一般情况下,作为开发人员会经常使用系统提供的内存管理基本函数,如malloc、realloc、calloc、free等,完成动态存储变量存储空间的分配和释放。但是,当开发程序中使用动态存储变量较多和频繁使用函数调用时,就会经常发生内存管理错误。

二、虚拟内存泄露

一般来说,我们观察系统的内存占用喜欢用top命令,然后输入m,对系统中整体的内存占用情况做个排序,然后在重点观察,内存占用排在前几位的进程,再逐步的分析。

[root@VM-0-2-centos ~]# top -p 5576
top - 18:21:46 up 198 days, 20:07,  2 users,  load average: 0.10, 0.04, 0.05
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.3 sy,  0.0 ni, 99.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1882008 total,    78532 free,   116516 used,  1686960 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  1606660 avail Mem PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                                 5576 root      20   0  184064  11248   1124 S  0.0  0.6  10:34.98 nginx   

虽然top 也可以观察到单独的进程的内存变化,不过一般不太好比较内存变化的规律,推荐使用pidstat工具,此工具需要先安装,通过命令:

yum install sysstat

pidstat 基本说明如下:

  • u:默认的参数,显示各个进程的cpu使用统计

  • r:显示各个进程的内存使用统计

  • d:显示各个进程的IO使用情况

  • p:指定进程号

  • w:显示每个进程的上下文切换情况

  • t:显示选择任务的线程的统计信息外的额外信息

  • T { TASK | CHILD | ALL }

假如我们观察到如下的内存占用情况:pidstat -r -p pid 5

[root@VM-0-2-centos ~]# pidstat -r -p 5981 5
Linux 3.10.0-1127.19.1.el7.x86_64 (VM-0-2-centos)   07/24/2021  _x86_64_    (1 CPU)06:25:55 PM   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command
06:26:00 PM     0      5981      0.20      0.00    4416    352   0.02  a.out
06:26:05 PM     0      5981      0.00      0.00    4416    352   0.02  a.out
06:26:10 PM     0      5981      0.20      0.00    4456    352   0.02  a.out
06:26:15 PM     0      5981      0.00      0.00    4456    352   0.02  a.out
06:26:20 PM     0      5981      0.00      0.00    4456    352   0.02  a.out
06:26:25 PM     0      5981      0.20      0.00    4496    352   0.02  a.out
06:26:30 PM     0      5981      0.00      0.00    4496    352   0.02  a.out
06:26:35 PM     0      5981      0.20      0.00    4536    352   0.02  a.out
06:26:40 PM     0      5981      0.00      0.00    4536    352   0.02  a.out
06:26:45 PM     0      5981      0.20      0.00    4576    352   0.02  a.out
06:26:50 PM     0      5981      0.00      0.00    4576    352   0.02  a.out
06:26:55 PM     0      5981      0.20      0.00    4616    352   0.02  a.out 

我们注意下,VSZ即虚拟内存的占用每10s增加40,单位为k,即10s增加40k的虚拟内存,下面来具体分析下这个程序的内存泄露情况。

三、分析泄露原因

我们来分析这个进程的内存分布情况,来分析这泄露的内存有什么特点:

[root@VM-0-2-centos ~]# pmap -x 5981
5981:   ./a.out
Address           Kbytes     RSS   Dirty Mode  Mapping
0000000000400000       4       4       0 r-x-- a.out
0000000000600000       4       4       4 r---- a.out
0000000000601000       4       4       4 rw--- a.out
00007faab436e000    2720     272     272 rw---   [ anon ]
00007faab4616000    1804     260       0 r-x-- libc-2.17.so
00007faab47d9000    2048       0       0 ----- libc-2.17.so
00007faab49d9000      16      16      16 r---- libc-2.17.so
00007faab49dd000       8       8       8 rw--- libc-2.17.so
00007faab49df000      20      12      12 rw---   [ anon ]
00007faab49e4000     136     108       0 r-x-- ld-2.17.so
00007faab4a06000    2012     212     212 rw---   [ anon ]
00007faab4c03000       8       8       8 rw---   [ anon ]
00007faab4c05000       4       4       4 r---- ld-2.17.so
00007faab4c06000       4       4       4 rw--- ld-2.17.so
00007faab4c07000       4       4       4 rw---   [ anon ]
00007ffe0f3f5000     132      16      16 rw---   [ stack ]
00007ffe0f47c000       8       4       0 r-x--   [ anon ]
ffffffffff600000       4       0       0 r-x--   [ anon ]
---------------- ------- ------- ------- 
total kB            8940     940     564

其中Address为开始的地址,Kbytes是虚拟内存的大小,RSS为真实内存的大小,Dirty为未同步到磁盘上的脏页,Mode为内存的权限,rw为可写可读,rx为可读和可执行。通过几次观察,我们发现:

00007faab436e000    2720     272     272 rw---   [ anon ]

为泄露部分,此为匿名内存区,也就是没有映射文件,为malloc或mmap分配的内存。同样是每次增加40K。

此时还是只能大概知道内存泄露的位置,我们还先找到具体的代码位置,这个该怎么分析?代码的申请,无非是通过malloc和brk这些库函数进行内存调用,我们可以用strace跟踪下。

[root@VM-0-2-centos ~]# strace -f -t -p 5981 -o trace.strace
strace: Process 5981 attached
strace: Process 8519 attached
strace: Process 8533 attached
strace: Process 8547 attached
strace: Process 8557 attached
strace: Process 8575 attached
^Cstrace: Process 5981 detached

我们通过-t选项来显示时间,-f来跟踪子进程。直接用cat命令查看跟踪的文件内容,会发现内容相当多,只要是系统调用都打印了出来,可以通过每次增加40k这个有用的信息搜索下:

[root@VM-0-2-centos ~]# grep 40960  trace.strace 
5981  19:01:44 mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7faab403a000
5981  19:01:55 mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7faab4030000
5981  19:02:06 mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7faab4026000
5981  19:02:17 mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7faab401c000
5981  19:02:28 mmap(NULL, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7faab4012000

至此我们找到了具体的泄露代码位置。看下这个测试代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#define _SCHED_H 
#define __USE_GNU 
#include <bits/sched.h>#define STACK_SIZE 40960int func(void *arg)
{printf("thread enter.\n");sleep(1);printf("thread exit.\n");return 0;
}int main()
{int thread_pid;int status;int w;while (1) {void *addr = mmap(NULL, STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0);if (addr == NULL) {perror("mmap");goto error;}printf("creat new thread...\n");thread_pid = clone(&func, addr + STACK_SIZE, CLONE_SIGHAND|CLONE_FS|CLONE_VM|CLONE_FILES, NULL);printf("Done! Thread pid: %d\n", thread_pid);if (thread_pid != -1) {do {w = waitpid(-1, NULL, __WCLONE | __WALL);if (w == -1) {perror("waitpid");goto error;}} while (!WIFEXITED(status) && !WIFSIGNALED(status));}sleep(10);}error:return 0;
}

这个测试程序利用mmap申请一块匿名私有的内存,clone为系统函数,pthread_create 和fork底层都是调用它,用来创建进程/线程,将func的地址指针存放在子进程堆栈的某个位置处,该位置就是该封装函数本身返回地址存放的位置,最后一个参数为func的执行参数。clone可以更灵活控制共享,比如可以控制是否共享内存空间,是否共享打开文件,是否共享相同的信号处理函数等。

我们可以看到,mmap申请内存后,需要通过munmap来释放,这里面没有释放,所以导致了虚拟内存泄露,这里面申请的内存只实际使用了4个字节,即复制了func的指针,其他的内存均没有使用,其实仔细观察会发现还有部分的物理内存泄露,每次4个字节,可以通过pmap -x 查到。

在 waitpid后面添加:munmap(addr,STACK_SIZE); 即可以实现内存的释放。

如何排查内存泄漏

我们平时开发过程中不可避免的会遇到内存泄漏问题,这是常见的问题。既然发生了内存泄漏,我们就要排查内存泄漏的问题。想必大家也经常会用到以下排查内存问题的工具,如下:
  • memwatch

  • mtrace

  • dmalloc

  • ccmalloc

  • valgrind

  • debug_new

四、valgrind 分析程序内存泄露

这个是比较常见的方法,一般通过下面命令来查看内存泄露:

valgrind --tool=memcheck --leak-check=full ./b[root@VM-0-2-centos test]# valgrind --tool=memcheck --leak-check=full ./b
==14374== Memcheck, a memory error detector
==14374== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14374== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==14374== Command: ./b
==14374== 
==14374== Warning: set address range perms: large range [0x5205040, 0x24605040) (undefined)
address:0x5205040
==14374== Warning: set address range perms: large range [0x5205040, 0x24605040) (defined)
524288000
==14374== 
==14374== HEAP SUMMARY:
==14374==     in use at exit: 524,288,000 bytes in 1 blocks
==14374==   total heap usage: 1 allocs, 0 frees, 524,288,000 bytes allocated
==14374== 
==14374== 524,288,000 bytes in 1 blocks are possibly lost in loss record 1 of 1
==14374==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==14374==    by 0x400675: main (test.c:17)
==14374== 
==14374== LEAK SUMMARY:
==14374==    definitely lost: 0 bytes in 0 blocks
==14374==    indirectly lost: 0 bytes in 0 blocks
==14374==      possibly lost: 524,288,000 bytes in 1 blocks
==14374==    still reachable: 0 bytes in 0 blocks
==14374==         suppressed: 0 bytes in 0 blocks

明确说明在test.c的17行有可能是内存泄露:==14374== by 0x400675: main (test.c:17)

五、AddressSanitizer(ASan)工具

AddressSanitizer(ASan)是一种内存错误检测工具,属于Clang/LLVM编译器工具套件的一部分。它用于检测和调试C/C++程序中的内存问题,如缓冲区溢出、使用已释放或未初始化的内存等。

ASan在编译时通过插入额外的代码来动态地检测程序运行过程中的内存访问错误。它会跟踪每个分配的内存块,并在程序执行期间监视对这些内存块的访问情况。如果发现任何非法操作,比如访问已释放或越界的内存,ASan将立即报告该错误,并提供有关问题位置和堆栈跟踪信息。

使用ASan可以帮助开发人员及早发现和修复潜在的内存错误,提高程序的稳定性和安全性。但需要注意,由于ASan会引入额外代码和运行时检查,可能会增加程序运行时的开销和内存占用量。它非常快,只拖慢程序两倍左右(比起Valgrind快多了)。它包括一个编译器instrumentation模块和一个提供malloc()/free()替代项的运行时库。从gcc 4.8开始,AddressSanitizer成为gcc的一部分。当然,要获得更好的体验,最好使用4.9及以上版本,因为gcc 4.8的AddressSanitizer还不完善,最大的缺点是没有符号信息。

使用方法:

  • 用-fsanitize=address选项编译和链接你的程序。

  • 用-fno-omit-frame-pointer编译,以得到更容易理解stack trace。

  • 可选择-O1或者更高的优化级别编译

gcc -fsanitize=address -o main -g main.c 

案例分析:

#include <iostream>int main() {int* arr = new int[5];// 内存访问错误 - 越界访问数组for (int i = 0; i <= 5; ++i) {arr[i] = i;}delete[] arr;return 0;
}

在使用ASan进行编译和运行时,你可以按照以下步骤:

(1)确保你已经安装了Clang/LLVM编译器。

(2)将上述代码保存到一个名为main.cpp的文件中。

(3)执行以下命令来编译程序,并启用ASan工具:

clang++ -fsanitize=address -g main.cpp -o test

(4)运行生成的可执行文件:

./test

当程序运行时,如果存在任何内存错误,ASan将会报告并显示相应的错误信息,包括错误位置、堆栈跟踪等。

六、其他内存泄露分析

其实上面的内存泄露是我们知道了具体的泄露的进程,然后再做详细分析。那么如果不知道哪里内存泄露了,有什么办法,可以通过分析meminfo文件,来观察泄露的类型。

[root@VM-0-2-centos test]# cat /proc/meminfo
MemTotal:        1882008 kB
MemFree:          752948 kB
MemAvailable:    1610108 kB
Buffers:          564900 kB
Cached:           399584 kB
SwapCached:            0 kB
Active:           808140 kB
Inactive:         220812 kB
Active(anon):      64548 kB
Inactive(anon):      488 kB
Active(file):     743592 kB
Inactive(file):   220324 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
....

‌meminfo文件‌是Linux系统中用于显示内存使用情况的详细信息文件,它位于/proc目录下,提供了关于系统内存使用的全面信息。通过查看和分析meminfo文件的内容,可以了解系统的内存使用状况,包括总内存、空闲内存、缓存、交换分区等信息,这对于排查内存相关的问题非常有帮助。

meminfo文件包含的主要信息及其含义如下:

  • ‌MemTotal‌:系统总内存大小。

  • ‌MemFree‌:系统空闲内存大小。

  • ‌MemAvailable‌:可用内存大小,包括空闲内存和缓存。

  • ‌Buffers‌:用于缓存数据的内存大小。

  • ‌Cached‌:用于缓存文件系统的内存大小。

  • ‌SwapCached‌:用于缓存交换分区的内存大小。

  • ‌Active‌ 和 ‌Inactive‌:分别表示活动和非活动内存大小,即正在使用或最近使用的内存和最近没有使用的内存。

  • ‌SwapTotal‌ 和 ‌SwapFree‌:交换分区总大小和空闲大小。

  • ‌Dirty‌ 和 ‌Writeback‌:等待写回到磁盘的内存大小和正在写回到磁盘的内存大小。

  • ‌AnonPages‌、‌Mapped‌、‌Shmem‌ 等:分别表示用于匿名映射、已映射到文件的内存、共享内存大小等。

  • ‌Slab‌、‌SReclaimable‌、‌SUnreclaim‌ 等:内核数据结构缓存的内存大小以及可回收和不可回收的Slab内存大小。

  • ‌KernelStack‌、‌PageTables‌ 等:内核栈的内存大小和页面表的内存大小。

  • ‌CommitLimit‌ 和 ‌Committed_AS‌:可用内存可支持的最大内存大小和已分配的内存大小,包括内存和交换分区。

  • ‌VmallocTotal‌、‌VmallocUsed‌ 等:虚拟内存总大小和已使用的虚拟内存大小。

排查内存问题时,可以通过以下步骤进行:

  • 首先,使用cat /proc/meminfo命令查看meminfo文件的内容,了解系统的整体内存使用情况。

  • 分析MemTotal和MemFree的值,了解系统的总内存和可用空闲内存。

  • 注意MemAvailable的值,它表示应用程序可用的内存,与MemFree的区别在于MemAvailable考虑了Buffers和Cached的大小,这些通常在系统需要时可以被回收。

  • 检查SwapUsage(虽然meminfo文件中没有直接显示SwapUsage,但可以通过SwapTotal和SwapFree计算得出),如果Swap空间被大量使用,可能意味着物理内存不足。

  • 注意Active、Inactive、Dirty和Writeback等值,这些指标可以帮助你了解系统当前的内存使用模式和可能的性能瓶颈。

  • 如果发现某些特定类型的内存使用异常高(如AnonPages、Shmem等),可能需要进一步调查这些类型的内存使用情况,以确定是否存在内存泄漏或其他问题。

  • 使用其他工具如freevmstattophtop等命令提供的信息与meminfo文件的内容进行对比,以获得更全面的系统内存使用情况视图。

通过综合分析meminfo文件的内容和其他相关工具的输出,可以有效地排查和解决Linux系统中的内存相关问题‌

相关文章:

内存泄漏的影响

(1)内存泄漏是什么&#xff1f; 内存泄漏是指程序运行过程中分配的内存没有被正确释放&#xff0c;导致这部分内存无法再次使用&#xff0c;从而造成内存资源的浪费。内存泄漏可能会导致系统性能下降、程序崩溃或者消耗过多的系统资源&#xff1b;内存泄漏通常发生在动态分配的…...

shell变量扩展你知道多少?

1. shell变量扩展 我们知道&#xff0c;${var}的形式可以获取变量var的值&#xff0c;但其实还可以有更多花式玩法。其中&#xff5e;表示用户根目录其实属于 波浪线扩展&#xff0c;这比较常见&#xff0c;不展开介绍了。 下面的每种情况中&#xff0c;word 都要经过波浪线扩…...

Compose中对于KeyEvent的处理

在开发Android TV时&#xff0c;遇到了一个需求&#xff0c;需要对遥控器发出的上下左右按键点击事件做处理。此处我们可以在Modifier.onKeyEvent中对按键事件做处理。此处我写了一个按钮的modifier模板如下。 private val buttonModifier Modifier.onKeyEvent {when {KeyEve…...

OpenXR Monado compositor处理应用layers(cheduled->delivered)

OpenXR Monado compositor处理应用的layer,scheduled->delivered @src/xrt/targets/common/target_instance.c t_instance_create_system @src/xrt/compositor/main/comp_compositor.ccomp_main_create_system_compositor@src/xrt/compositor/multi/comp_multi_system…...

leetcode:1137 Tribonacci 数列

1137 Tribonacci 数列 题目链接https://leetcode.cn/problems/n-th-tribonacci-number/ 题目描述 Tribonacci 数列是一种类似于斐波那契数列的数列&#xff0c;不同之处在于&#xff0c;Tribonacci 数列中的每一项是前面三项的和。给定整数 n&#xff0c;求出 Tribonacci 数…...

简单讲一下API的作用以及介绍

API全称Application Programming Interface&#xff0c;即应用程序编程接口&#xff0c;是一些预先定义的函数&#xff0c;或指软件系统不同组成部分衔接的约定&#xff0c;用于传输数据和指令&#xff0c;使应用程序之间可以集成和共享数据资源。 API 接口简介 一、基本概念…...

猎板道出PCB免费打样真相:制造成本究竟给了谁?

猎板PCB作为电路板特殊定制的厂家&#xff0c;曾经推出了PCB免费打样活动以吸引新客户。从经营的角度来看&#xff0c;免费打样的成本实际上最终由稳定客户承担。免费打样的客户往往仅在有免费机会时下单&#xff0c;而稳定的合作客户则为这些促销活动买单。这种模式长期下来可…...

Linux 竞争与并发(学习总结)

在Linux驱动开发中&#xff0c;“并发”和“竞争”是两个重要的概念&#xff0c;它们涉及到多任务环境下资源的管理和使用。 并发 (Concurrency) 并发指的是在同一时间段内&#xff0c;多个任务看似同时运行的现象。实际上&#xff0c;在单核处理器上&#xff0c;这通常是通过…...

SaaS初创企业需求建模指南

所以你已经准备好进入市场&#xff0c;你有宏大的目标&#xff0c;并且充满激情。 但等等。 你要如何 实现 这些目标呢&#xff1f; 你设置了 正确的 目标吗&#xff1f; 而且你的目标是 可实现的吗&#xff1f; 那么&#xff0c;如何回答这些问题呢&#xff1f; 进入需求…...

MySQL最左匹配原则

MySQL索引的加左原则&#xff0c;也被称为最左匹配原则&#xff08;Leftmost Prefix Rule&#xff09;或最左前缀规则&#xff08;Leftmost Prefixes&#xff09;&#xff0c;是指在创建复合索引时&#xff0c;应将经常用于查询的列放在索引的最左边&#xff0c;以便MySQL能够更…...

日常开发1:居中处理

开发的时候总会遇到两个空间上下两层,然后居中排放,如果只是知道下方或者上方控件的具体位置点,但是不知道另外一个控件的集体点位,应该怎么处理呢? 如上图所示,知道imageview 下方中间的点的位置(这里暂时定义image的宽高已知),上方是textview,那么如何布局呢? 简单解决方法…...

css弹性盒子——flex布局

目录 ​编辑 一、flex容器的样式属性(父元素属性) display:flex 弹性盒子&#xff0c;实现水平排列,在父盒子设置&#xff0c;适用于单行/单列 justify-content 二、flex元素的样式属性(子元素属性) 1.flex-grow 2.flex-shrink 3.flex-basis 4.flex组合属性 flex:flex-…...

亚马逊云科技 Gen BI 2024-09-04 上海站QuickSight

机缘 我又来了&#xff0c;感觉不上班比上班还要忙 天天像特种工一天&#xff0c;今天有度过的充实的一天&#xff0c;上午去图书馆&#xff0c;下午去了 亚马逊云科技 Gen BI 技术体验日 。 具体照片可以去 这里看 哈哈&#xff0c;这个就是我了 商业智能的趋势 根据艾瑞咨…...

【Qt】Qt和JavaScript使用QWebChannel交互

问题 问题一&#xff1a; 问题描述&#xff1a;运行时&#xff0c;Qt向Js端发送消息没有问题&#xff0c;Js端向Qt端发送消息时失败 报错&#xff1a;Cannot invoke unknown method of index -1 on object webTransport(0x…) 原因及解决办法&#xff1a;使用Qt 5.11.2编译生…...

码住!15个爆好用知识库软件工具分享

市场趋势&#xff1a;全球知识库管理软件的市场规模发展速度非常快&#xff0c;并且未来几年内仍将继续保持增长。据Verified Market Research预测&#xff0c;2028年知识库管理软件的全球市场份额将增长到588.1亿美元&#xff0c;复合年增长率达12.67%。 知识库软件可以帮助企…...

MybatisPlus中@EnumValue注解介绍、应用场景和示例代码

EnumValue注解详细介绍 功能概述&#xff1a; EnumValue注解标记在枚举类型的字段上&#xff0c;表示该字段是枚举值在数据库中存储的实际值。这对于枚举的持久化是关键&#xff0c;确保枚举在数据库中的表示与Java枚举类的一致性。 主要用途&#xff1a; 字段指定&#xff1a;…...

【计算机网络】描述TCP建立连接与断开的过程

一、TCP连接的建立与断开 1、建立连接——三次握手 1、A的TCP向B发出连接请求报文段 其首部中的同步位SYN 1&#xff0c;并选择序号seq x&#xff0c;表明传送数据时的第一个数据字节的序号是 x 2、B的TCP收到连接请求报文段后&#xff0c;如同意&#xff0c;则发回确认。 B …...

CSS学习14[重点]

定位 前言一、定位二、定位模式1. 静态定位 static2. 相对定位 relative3. 绝对定位 absolute4. 子绝父相5. 绝对定位的盒子水平居中 6. 固定定位&#xff08;fixed&#xff09;7. 叠放次序&#xff08;z&#xff09;三、四种定位总结四、定位模式转换 前言 为什么学习定位&am…...

力扣 | 递归 | 区间上的动态规划 | 486. 预测赢家

文章目录 一、递归二、区间动态规划 LeetCode&#xff1a;486. 预测赢家 一、递归 注意到本题数据范围为 1 < n < 20 1<n<20 1<n<20&#xff0c;因此可以使用递归枚举选择方式&#xff0c;时间复杂度为 2 20 1024 ∗ 1024 1048576 1.05 1 0 6 2^{20…...

黑白格

题目描述 小杨有一个 n 行 m 列的网格图&#xff0c;其中每个格子要么是白色&#xff0c;要么是黑色。 小杨想知道至少包含 k 个黑色格子的最小子矩形包含了多少个格子。 输入格式 第一行包含三个正整数 n,m,k&#xff0c;含义如题面所示。 之后 n 行&#xff0c;每行⼀个…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...