内存不足引发C++程序闪退崩溃问题的分析与总结

目录

1、内存不足一般出现在32位程序中

2、内存不足时会导致malloc或new申请内存失败

2.1、malloc申请内存失败,返回NULL

2.2、new申请内存失败,抛出异常

3、内存不足项目实战案例中相关细节与要点说明

3.1、内存不足导致malloc申请内存失败,导致程序闪退

3.1.1、内存不足导致程序闪退的原因

3.1.2、abort强制终止进程导致程序闪退时,不会生成dump文件

3.2、内存不足导致new申请内存时抛出异常,引发程序崩溃

4、引发内存不足的两个原因

4.1、32位程序默认的用户态虚拟内存只有2GB,程序模块较多,可能占用的内存接近2GB了

4.2、程序中有内存泄漏,且内存泄漏的代码在不断的执行,导致程序占用内存越来越多

5、解决内存不够用的办法

6、最后


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/125529931C/C++实战进阶(已更新到460多篇,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/140824370VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/124272585Windows C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_12695902.htmlC++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_2276111.html       最近在项目中遇到几个因为内存不足引发程序闪退或崩溃的问题,比较有代表性,所以本文在此总结一下内存不足的相关问题场景以及内存不足引发程序异常的具体原因,供大家借鉴或参考。

1、内存不足一般出现在32位程序中

       C++程序按位数可以分为32位和64位程序。对于64位程序,内存地址按64位寻址,系统会给64位程序分配0-0xFFFFFFFFFFFFFFFF这个范围的虚拟地址。而对于32位程序,内存地址按32位寻址,系统会给32位程序分配0-0xFFFFFFFF这个范围的虚拟内存,即4GB虚拟内存。所以系统给64位程序分配的虚拟内存空间要比32位程序大的多,几乎是“用之不竭”的,所以内存不足基本是出现在32位程序中。

       对于32位程序,系统在其启动时分配4GB的虚拟内存,默认情况下,用户态虚拟内存和内核态虚拟内存各占2GB,而C++程序基本都运行在用户态,用户态虚拟内存只有2GB,当占用内存的模块很多或者有内存泄漏时,很容易接近这个2GB的上限,从而出现内存不足的问题,进而导致程序发生闪退或崩溃。

虽然系统给64程序分配的虚拟内存非常大,但在有内存泄漏的情况下也可能会出现内存不足的问题。比如程序一直在持续的运行(程序不关闭),且在持续的发生内存泄漏,则再大的虚拟内存空间也有用尽的那一刻。

2、内存不足时会导致malloc或new申请内存失败

       C++程序在运行过程中主要使用全局内存、栈内存和堆内存,而全局内存是在程序启动时(进入main函数之前)就分配好了,栈内存和堆内存则是在程序运行过程中分配或申请的。栈内存则是和线程相关的,在创建线程时系统会给线程分配指定大小的栈内存,线程中调用的函数中的局部变量使用的都是栈内存。

在Windows系统中,系统默认给线程分配1MB的栈空间;在Linux系统中,系统默认给线程分配8MB的栈空间。线程中调用的函数会使用线程的栈空间,如果当前线程中调用的函数占用的总的栈空间超过系统分配给系统的上限,则会导致Stack oveflow线程栈溢出的异常,导致程序崩溃。关于引发Stack oveflow线程栈溢出的常见原因及详细说明,可以查看我的文章:

通过Stack Overflow线程栈溢出的问题实例,详解C++程序线程栈溢出的诸多细节icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/140908516

       线程占用的栈空间相对不多,C++程序中使用更多的还是堆内存,所以我们此处主要讨论内存不足对申请堆内存的影响。C++程序中主要使用C函数malloc或者new操作符去申请堆内存,当内存不足时使用malloc和new的反应是有所不同的:

1)malloc申请内存失败时会返回NULL;

2)new申请内存失败时会抛出异常,导致程序发生崩溃。

       在Windows C++程序中,除了使用new去申请堆内存,还可以调用Windows系统API函数HeapAlloc从堆上分配内存(要用HeapFree去释放),还可能调用API函数VirtualAlloc或VirtualAllocEx从虚拟内存上分配内存(要用VirtualFree或VirtualFreeEx去释放),还可能调用其他的API函数。本文主要讨论使用new的场景。

2.1、malloc申请内存失败,返回NULL

       malloc申请内存失败时,会返回NULL,通过这个NULL返回值就可以判断内存申请失败了。

       malloc申请内存失败,可能会引发程序发生闪退(注意内存申请失败本身不会导致程序闪退崩溃)。之前我们在项目中就遇到过,我们的程序使用了开源的WebRTC库,当时程序中有内存泄漏,内存不够用了,导致WebRTC开源库内部代码在调用malloc申请内存时失败了,malloc返回NULL,WebRTC内部判断malloc返回NULL,认为这个是fatal致命的(因为申请不到内存,业务没法正常的展开,WebRTC内部认为这是致命的),直接调用abort强行将当前进程终止了,相关代码如下

RTC_CHECK宏会校验malloc的返回值,如下: 

如果malloc返回的地址为空,则会调用rtc_FatalMessage接口: 

 rtc_FatalMessage接口内部会调用FatalLog

FatalLog接口中会在末尾处先是调用DebugBreak接口,如果当前程序正在调试,则DebugBreak会让调试器中断下来(从DebugBreak函数名就能看出这个函数的作用),目的是让正在调试的用户感知到!然后紧接着会调用abort接口,将当前进程强制终止掉!

       其实abort接口内部也会让正在调试的调试器中断下来,abort的内部实现代码如下所示:

/***
*void abort() - abort the current program by raising SIGABRT
*
*Purpose:
*   print out an abort message and raise the SIGABRT signal.  If the user
*   hasn't defined an abort handler routine, terminate the program
*   with exit status of 3 without cleaning up.
*
*   Multi-thread version does not raise SIGABRT -- this isn't supported
*   under multi-thread.
*******************************************************************************/
void __cdecl abort (void)
{_PHNDLR sigabrt_act = SIG_DFL;#ifdef _DEBUGif (__abort_behavior & _WRITE_ABORT_MSG){/* write the abort message */_NMSG_WRITE(_RT_ABORT);}
#endif  /* _DEBUG *//* Check if the user installed a handler for SIGABRT.* We need to read the user handler atomically in the case* another thread is aborting while we change the signal* handler.*/sigabrt_act = __get_sigabrt();if (sigabrt_act != SIG_DFL){raise(SIGABRT);}/* If there is no user handler for SIGABRT or if the user* handler returns, then exit from the program anyway*/if (__abort_behavior & _CALL_REPORTFAULT){_call_reportfault(_CRT_DEBUGGER_ABORT, STATUS_FATAL_APP_EXIT, EXCEPTION_NONCONTINUABLE);}/* If we don't want to call ReportFault, then we call _exit(3), which is the* same as invoking the default handler for SIGABRT*/_exit(3);
}

从上述代码可以看出,abort内部调用了raise(SIGABRT),该函数是触发一个SIGABRT信号终止异常,如果当前正在调试状态,会让调试器中断下来。最后调用了C函数_exit退出当前进程。 

       注意,上述问题中并没有产生C++异常,是调用abort强行终止进程的,程序直接闪退消失了,给人感觉是程序崩溃了,实际上并不是崩溃!这个项目问题案例,我之前专门写了文章,可以去查看文章:

WebRTC开源库内部调用abort函数引发C++程序发生闪退问题的详细排查icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/129460580       对于这种调用abort强行终止进程的问题,还有一个细节值得注意一下。如果程序中安装了异常捕获,此种场景下是不会生成dump文件的。因为当前是WebRTC开源库内部检测到malloc返回NULL,直接调用abort,程序并没有发生C++上的异常,所以异常捕获是感知不到的(发生C++上的异常,异常捕获模块才能感知到),虽然给人一种程序发生崩溃闪退的感觉,但不会生成dump文件的。


        在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:该精品技术专栏的订阅量已达到560多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2:(本专栏涵盖了C++多方面的内容,是当前重点打造的专栏,订阅量已达210多个,专栏文章已经更新到470多篇,持续更新中...)

C/C++实战进阶(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与项目实战进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域多个方面的内容,包括C++基础及编程要点(模版泛型编程、STL容器及算法函数的使用等)、数据结构与算法、C++11及以上新特性(不仅看开源代码会用到,日常编码中也会用到部分新特性,面试时也会涉及到)、常用C++开源库的介绍与使用、代码分享(调用系统API、使用开源库)、常用编程技术(动态库、多线程、多进程、数据库及网络编程等)、软件UI编程(Win32/duilib/QT/MFC)、C++软件调试技术(排查软件异常的手段与方法、分析C++软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等)、设计模式、网络基础知识与网络问题分析进阶内容等。

专栏3:  

C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏4:   

VC++常用功能开发汇总(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_12695902.html

根据多年C++软件开发实践,详细地总结了C/C++软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。


2.2、new申请内存失败,抛出异常

       当程序内存不足时,使用new去动态申请内存失败,默认情况下会抛出bad_alloc内存申请失败的异常。这种场景是产生了异常,如果程序中安装了异常捕获模块,且异常捕获模块感知到了,会生成dump文件的。比如我们有次遇到因为内存泄漏导致内存不足导致new抛出了异常,用Windbg打开dump文件,在函数调用堆栈中看到了程序中抛出了bad_alloc异常,如下所示:

从堆栈上可以看出,抛出bad_alloc异常的代码就是new那句代码抛出的是std::bad_alloc异常,就是我们讲的bad_alloc异常,导致程序发生崩溃闪退(代码中没有对这个bad_alloc异常进行处理)。

如果dump文件中显示new时抛出了bad_alloc异常,可能是内存不足导致的,可以怀疑程序中可能存在内存泄漏,然后使用工具观察程序运行过程中的内存变化,去确定是否真的是内存泄漏导致的!

       这里还有一个细节,new失败抛出bad_alloc异常,不一定是内存不足导致的。也可能是程序中有堆内存越界,导致堆内存被破坏引发的。堆内存被破坏,会导致程序导出胡乱的崩溃,一会再new的地方,一会在delete的地方。堆内存被破坏的异常,是最难查的一类异常!

       对于new失败时抛出bad_alloc异常导致程序崩溃,我们可以让new不要抛出异常,而是像malloc一样在申请内存失败时返回空指针,使用std::nothrow指定new不要抛出异常,如下:

#include <iostream>int main(){char *p = NULL;int i = 0;do{p = new(std::nothrow) char[10*1024*1024]; // 每次申请10MBi++;Sleep(5);}while(p);if(NULL == p){std::cout << "分配了 " << (i-1)*10 << " M内存"         //分配了 1890 Mn内存第 1891 次内存分配失败           << "第 " << i << " 次内存分配失败";}return 0;
}

此外,还可以使用try...catch来捕获异常:(因为异常被捕获处理了,程序也就不会再崩溃了)

#include <iostream>
using namespace std;int main(){char *p;int i = 0;try{do{p = new char[10*1024*1024];i++;Sleep(5);}while(p);}catch(const std::exception& e){std::cout << e.what() << "\n"<< "分配了" << i*10 << "M" << std::endl;}return 0;   
}

虽然上面两种做法,都能让程序不再崩溃,但程序进程内存不足,业务已经没法正常展开和执行了,让程序还活着,意义也不大了。 

3、内存不足项目实战案例中相关细节与要点说明

       最近遇到的两个问题案例都是内存不足导致的,一个是程序占用的虚拟内存接近进程的用户态虚拟内存上限导致的,一个是程序中发生了内存泄漏引发的。这两个案例中,一个是内存不足导致了WebRTC内部malloc申请内存失败导致程序发生闪退,一个是内存不足导致了new内存时抛出了异常引发了程序崩溃。下面讲一下这两个案例涉及的细节和要点。

3.1、内存不足导致malloc申请内存失败,导致程序闪退

3.1.1、内存不足导致程序闪退的原因

       我们32位程序占用了大量的虚拟内存,可能快接近程序的2GB用户态虚拟内存的上限,从而导致WebRTC库内部使用malloc申请内存时出现失败的问题!WebRTC内部可能认为malloc申请内存失败是Fatal致命的,因为相关业务无法正常展开了。然后会直接调用abort接口强行将当前进程终止掉,这样程序就闪退了。具体的代码及逻辑说明已经在上面的2.1节中详细讲述了,这里就不再展开了。

3.1.2、abort强制终止进程导致程序闪退时,不会生成dump文件

       调用abort强行终止进程,程序闪退,给人一种程序发生崩溃的感觉,其实程序中并没有产生C++异常,并没有产生崩溃,所以程序中安装的异常捕获模块没有感知到(只有发生异常才会感知到),所以就没有生成dump文件。所以,项目中如果遇到程序闪退时没有产生dump文件,可能是调用abort函数强行终止进程引起的。

       有时我们会尝试到系统的应用程序日志中查找程序崩溃的日志,因为日志中可能会记录程序AppCrash的记录,记录中可能会有dump文件的信息(包括dump文件的路径)。系统在感知到程序异常崩溃时,可能会自动生成包含异常上下文的dump文件。之前在项目中遇到的崩溃,到应用程序日志中查看到dump文件的信息。对于那些

       所以,当程序发生闪退且没有生成dump文件时,可能是内存不足导致内存申请失败,程序中调用了abort强行终止进程导致的。对于这类问题,如果好复现,可以将Windbg附加到进程上进行动态调试,abort的调用会让Windbg中断下来,然后去查看此刻的函数调用堆栈就可以找出原因了,对应的案例,可以查看我的文章:

基于WebRTC构建的C++程序因虚拟内存不足导致闪退问题的排查以及解决办法的探究icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/133973572

3.2、内存不足导致new申请内存时抛出异常,引发程序崩溃

       内存不足导致new申请内存失败,抛出异常,如果程序中安装了异常捕获模块,异常捕获模块就会感知到程序发生了异常。以我们项目遇到的一个问题为例,程序崩溃后取来了dump文件,用Windbg打开,查看异常发生的函数调用堆栈:

就是new时抛出了bad_alloc的异常,就是内存不足引起的。是因为程序中发生了内存泄漏,导致的内存不足。

       对于引发C++程序内存泄漏的原因分析与排查方法,之前做过详细的总结,可以查看我之前写的文章:

引发C++程序内存泄漏的原因分析与排查方法总结icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/141403867       内存泄漏问题,有时排查起来会很费劲,可以借助一些工具去排查,比如使用Windbg、VLD、Debug Diagnostic Tool、Valgrind和AddressSanitizer等。

       关于VLD检测内存泄漏的完整案例,可以查看我的文章:

使用Visual Leak Detector(VLD)排查C++程序内存泄漏icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/135472681       关于Debug Diagnostic Tool检测内存泄漏的案例,可以查看我的文章:

使用Debug Diagnostic Tool工具排查C++程序内存泄漏问题icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/80075888       关于Windbg检测内存泄漏的案例,可以查看我的文章:
使用Windbg排查C++程序内存泄漏问题icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/121295720使用 Windbg 的 !heap 命令分析内存泄漏icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/131576063       内存泄漏点的定位,还可以使用历史版本比对法,相关方法可以查看我之前写的一篇类似的文章:

使用历史版本比对法排查C++程序中的内存泄漏问题icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/141002375此处的历史版本比对法,是排查C++软件异常的一个重要方法,之前对排查C++软件异常的常用手段与方法进行过详细的总结,可以查看我之前写的文章

排查C++软件异常的常见思路与方法(实战经验总结)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/120629327       关于Linux系统上的Valgrind和AddressSanitizer工具,可以查看我的文章:(微软从Visual Stdio 2019 19.6版本开始引入Google的AddressSanitizer内存检测工具,下面的文章有讲到)

Windows和Linux下排查C++软件异常的常用调试器与内存检测工具详细介绍icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/126381865为什么选择C/C++内存检测工具AddressSanitizer?如何使用AddressSanitizer?icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/132863447       有时使用一个工具可能无法定位内存泄漏问题,可能需要尝试使用多个内存检测工具去排查,之前记录了内存泄漏排查的专题,感兴趣也可以去看看:

​ C++内存泄漏排查icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/category_12370029.html

4、引发内存不足的两个原因

       导致程序产生内存不足,从项目中遇到的问题案例来看,主要有两种原因:

1)程序占用了大量的虚拟内存,接近给程序进程分配的虚拟内存的上限。

2)程序中发生了内存泄漏,导致程序占用的虚拟内存越来越大,接近或达到给程序进程分配的虚拟内存上限。

4.1、32位程序默认的用户态虚拟内存只有2GB,程序模块较多,可能占用的内存接近2GB了

       32位程序启动时,系统会给程序分配4GB的虚拟内存,用户态和内核态默认各占2GB。如果程序中的模块比较多,或者引入了消耗内存很大的模块后,会导致主程序占用的内存很大,甚至接近用户态2GB虚拟内存的上限(程序的业务模块基本都运行在用户态中,占用的都是用户态的虚拟内存)。再执行比较耗内存的操作时,可能会导致更接近或达到2GB用户态虚拟内存的上限,导致内存不足,进而导致程序出问题。

       规避的办法是,修改主程序的工程配置,启动大地址模式,将用户态虚拟内存从默认的2GB上调到3GB,这样可以有效地缓解内存不够用的问题。关于如何在Visual Studio中配置大地址模式,可以查看我之前写的文章:

如何配置32位C++程序启用大地址模式(将用户态虚拟内存从2GB扩充到3GB),以解决用户态虚拟内存不够用问题?(项目实战案例解析)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/138460583

4.2、程序中有内存泄漏,且内存泄漏的代码在不断的执行,导致程序占用内存越来越多

       程序中有内存泄漏,内存泄漏的代码频繁地被执行,或者用户多次执行内存泄漏的代码(也可能是测试人员进行拷机测试,比如不断的入会退会,前端时间我们就遇到过这个问题场景),导致程序占用的内存越来越多,最后导致内存不足。对于内存泄漏,可以使用Process Explorer工具持续地查看程序虚拟内存的变化,确定是否存在内存泄漏。找到内存泄漏的点并加以解决,就可以解决这类问题。

       关于内存泄漏的排查,可以用历史版本比对法,也可以使用一些工具进行排查,上面已经讲到了,我就不再赘述了。

5、解决内存不够用的办法

       我们先要确定引发内存不足的原因,然后针对原因和场景,提出对应的解决办法。如果程序中有内存泄漏,则要解决内存泄漏。如果程序是32位的,确实包含多个模块,占用的内存比较大,则有以下几个方法:

1)优化程序内存占用

对程序中的内存占用进行优化,减小内存的占用。
2)扩充用户态虚拟内存

可以修改主工程的工程属性,将用户态的虚拟内存从2GB扩大到3GB,用规避的方法加以解决,如何扩充,可以查看我之前写的专题文章:

如何配置32位C++程序启用大地址模式(将用户态虚拟内存从2GB扩充到3GB),以解决用户态虚拟内存不够用问题?(项目实战案例解析)icon-default.png?t=O83Ahttps://blog.csdn.net/chenlycly/article/details/1384605833)将程序升级到64位

可以将程序升级到64位,但这里有个问题。虽然大家使用的基本都是Win10及以上的系统,都是64位的,但有的用户的电脑用的系统比较老,比如还在用Win7,可能还是32位的。做成64位程序,则没法在32位系统中运行。
4)做成多进程模式

可以做成多进程,但多进程加大了程序的开发难度,使得开发难度和成本都变高了。有的程序就做成了多进程模式,最具代表性的就是Chrome浏览器,就做成了多进程模式,每个进程负责执行不同的事务。

6、最后

       本文从最近遇到的两个内存不足导致程序异常的案例出发,详细讲述了案例中涉及到的细节与要点,并对内存不足相关内容进行了展开和总结,有一定的实战参考价值,希望能帮到大家。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/478267.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之代理模式(模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景)

前言&#xff1a; 写写CRUD&#xff0c;不会的百度一下&#xff0c;就完事了&#xff0c;总觉得别人问的东西像在造火箭一样。但在高体量、高并发的业务场景下&#xff0c;每一次的压测优化&#xff0c;性能提升&#xff0c;都像在研究一道数学题一样&#xff0c;反复的锤炼&am…

Java项目实战II基于微信小程序的图书馆自习室座位预约平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 在知识爆炸的时代&#xff0c;图书馆和…

【机器学习】——卷积与循环的交响曲:神经网络模型在现代科技中的协奏

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

智慧社区管理系统平台提升物业运营效率与用户体验

内容概要 智慧社区管理系统平台是一个集成了多项功能的综合性解决方案&#xff0c;旨在通过先进的技术手段提升物业管理的效率和居民的生活质量。该平台不仅关注物业运营的各个方面&#xff0c;还强调用户体验的重要性。随着科技的发展&#xff0c;社区管理方式正发生着翻天覆…

使用脚本实现hadoop-yarn-flink自动化部署

本文使用脚本实现hadoop-yarn-flink的快速部署&#xff08;单机部署&#xff09;。 环境&#xff1a;①操作系统&#xff1a;CentOS 7.6&#xff1b;②CPU&#xff1a;x86&#xff1b;③用户&#xff1a;root。 1.前置条件 把下面的的脚本保存到“pre-install.sh”文件&#x…

【vue】vue中插槽slot的用法详解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

爬虫获取的数据如何用于市场分析?

在数字化时代&#xff0c;数据已成为企业决策的重要资产。通过爬虫技术获取的数据可以为市场分析提供丰富的原材料。本文将探讨如何利用Python爬虫获取的数据进行市场分析&#xff0c;并提供代码示例。 1. 数据收集 首先&#xff0c;我们需要通过爬虫收集相关数据。以电商行业…

Linux高阶——1123—服务器基础服务器设备服务器基础能力

目录 1、服务器基础 1、服务器基本概述 2、服务器设计之初解决的问题 网络穿透 网络数据设备间的收发 3、服务器的类型C/S、B/S 2、服务器设备 将自己的服务器软件部署上线 3、代理服务器负载均衡&#xff0c;以及地址绑定方式 4、服务器的基础能力 1、服务器基础 1…

DICOM图像深入解析:为何部分DR/CR图像默认显示为反色?

概述 在数字医学影像处理中,CR(Computed Radiography,计算机放射摄影)和DR(Digital Radiography,数字放射摄影)技术广泛应用于医疗影像获取与分析。然而,临床实践中常常遇到这样一个问题:部分CR/DR图像在默认打开时呈现为反色(即负片效果),需手动反色后才能正常阅片…

公网弹性绑定负载均衡收费吗?

公网弹性绑定负载均衡收费吗&#xff1f;公网弹性绑定负载均衡&#xff08;ELB&#xff09;是收费的。费用主要包括公网IP费、带宽费和负载均衡实例费。其中&#xff0c;带宽费可以按固定带宽或实际使用流量计费&#xff0c;而实例费则根据类型、规格和使用时长来定价。此外&am…

【ArcGISPro】根据yaml构建原始Pro的conda环境

使用场景 我们不小心把原始arcgispro-py3的conda环境破坏了,我们就可以使用以下方法进行修复 查找文件 在arcgis目录下找到yaml文件 如果没找到请复制以下内容到新的yaml文件 channels: - esri - defaults dependencies: - anyio=4.2.0=py311haa95532_0 - appdirs=1.4.4=p…

多头数(head number);d_model、d_k;词嵌入维度之间的关系;多头是对不同维度的特征分开提取,意义在于将并行执行

目录 多头是对不同维度的特征分开提取,意义在于将并行执行 之后的每头提取的特征仅仅进行矩阵拼接 多头数(head number) d_model、d_k 词嵌入维度之间的关系 词嵌入的维度(d_model)决定了权重矩阵的形状 一、概念解释 二、关系举例说明 多头数,权重矩阵的长度和词…

【Google Cloud】Private Service Connect 托管式服务

简介 Private Service Connect 是什么 Private Service Connect 是 Google Cloud&#xff08;原名 GCP&#xff09;Virtual Private Cloud&#xff08;VPC&#xff09;的一项功能。 该功能主要用于以下两个场景&#xff1a; 使用私有 IP 访问 Google Cloud 的 API。将用户自…

【redis 】string类型详解

string类型详解 一、string类型的概念二、string类型的常用指令2.1 SET2.2 GET2.3 MSET2.4 MGET2.5 SETNX2.6 INCR2.7 INCRBY2.8 DECR2.9 DECRBY2.10 INCRBYFLOAT2.11 APPEND2.12 GETRANGE2.13 SETRANGE2.14 STRLEN 三、string类型的命令小结四、string类型的内部编码五、strin…

跨平台应用开发框架(1)----Qt(组件篇)

目录 1.Qt 1.Qt 的主要特点 2.Qt的使用场景 3.Qt的版本 2.QtSDK 1.Qt SDK 的组成部分 2.安装 Qt SDK 3.Qt SDK 的优势 3.Qt初识 1.快速上手 widget.cpp mian.cpp widget.h Helloworld.pro 2.对象树 3.坐标系 4.信号和槽 1. 信号和槽的基本概念 2. 信号和槽的…

Element UI 打包探索【2】

目录 第三个命令 第四个命令 第五个命令 第六个命令 第七个命令 cross-env BABEL_ENV babel 第八个命令 总结 书&#x1f4da;接上文Element UI 打包探索【1】我们继续来看 第三个命令 "lint": "eslint src/**/* test/**/* packages/**/* build/**/* …

JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)

目录 JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能&#xff0c;JS中排序算法的使用详解&#xff08;附实际应用代码&#xff09; 一、为什么要使用Array.sort() 二、Array.sort() 的使用与技巧 1、基础语法 2、返回值 3、…

丹摩 | 利用 CogVideoX 生成视频

声明&#xff1a;非广告&#xff0c;纯用户体验 1. CogVideoX CogVideoX 是智谱 AI 推出的一款极具创新性与突破性的视频生成产品。它在技术层面展现出诸多卓越特性&#xff0c;例如其采用的 Diffusion Transformer&#xff08;DiT&#xff09;架构奠定了强大的生成能力基础…

SAP开发语言ABAP常见面试问题及答案

一、基础概念问题 什么是SAP ABAP&#xff1f; SAP ABAP&#xff08;Advanced Business Application Programming&#xff09;是一种高级企业应用编程语言&#xff0c;用于开发SAP系统中的应用程序。它主要用于定制和扩展SAP的标准功能&#xff0c;以满足企业特定的业务需求。例…

C# 读取多条数据记录导出到 Word标签模板之图片输出改造

目录 应用需求 设计 范例运行环境 配置Office DCOM 实现代码 组件库引入 ​核心代码 调用示例 小结 应用需求 在我的文章《C# 读取多条数据记录导出到 Word 标签模板》里&#xff0c;讲述读取多条数据记录结合 WORD 标签模板输出文件的功能&#xff0c;原有输出图片的…