Linux —— 信号(3)

Linux —— 信号(3)

  • Core dump
  • 为什么core默认是被关闭的
  • 阻塞信号
    • 信号其他相关常见概念
    • 信号递达
    • 信号未决
    • 信号阻塞
    • 两者的区别
    • 信号的结构
  • 信号集操作函数
  • 一个简单使用例子
  • sigpending的使用例子

我们今天接着来了解信号:

Core dump

大家不知道有没有留意过,如果有 / 0 的错误,一般会报这个错误:

#include <stdio.h>  
#include <stdlib.h>  
#include <signal.h>  
#include <unistd.h>  
#include <cstring>
#include<iostream>int main()
{int b = 10;int a = b / 0;return 0;
}

在这里插入图片描述
我们可以在7号手册里查看signal的一些信息:
在这里插入图片描述
action这一栏,如果有core的话,一般会触发Core dump(核心转储)。

Core dump,中文可译作“核心转储”或通俗地称为“吐核”,是在计算机科学中一个术语,特指当一个程序异常终止(由于错误、异常或收到特定信号)时,操作系统捕捉该程序当时的内存状态,并将其保存到一个文件中,这个文件即称为core dump文件。此操作允许开发者事后分析程序崩溃的原因。

Core dump文件包含但不限于以下信息:

  • 进程执行时的内存内容,即程序崩溃瞬间的“内存快照”。
  • 寄存器状态,包括程序计数器、栈指针等,这对于重建程序执行流程至关重要。
  • 内存管理信息,帮助理解程序如何使用分配的内存。
  • 其他处理器和操作系统相关状态信息。

这些信息对于调试非常宝贵,因为它们可以帮助程序员确定导致程序失败的确切原因,尤其是在那些难以复现的错误场景中。通过使用如GDB(GNU Debugger)这样的调试工具,开发者可以加载core dump文件和相应的可执行文件,逐步检查程序崩溃时的状态,进而定位和修复错误。

我们可以用ulimit -a查看我们关于core dump的设置:
在这里插入图片描述这里的core file设置为0,表明在触发时不会生成core file,如果我们想让它生成core file文件,我们要对其进行设置:

ulimit -c 大小

这样可以临时在当前会话中开辟core file的文件大小,这里注意一下,这只是临时设置,如果重新登录,就会重新归0。

在这里插入图片描述
这个时候运行程序:
在这里插入图片描述
在比较新的Centos中,core 文件会存放在这个路径下:
在这里插入图片描述我们看看下面有哪些文件:
在这里插入图片描述
得到了一个zst的压缩文件,我们解压一下:
在这里插入图片描述
然后我们开启gdb:
在这里插入图片描述然后我们执行以下命令:

core-file 文件名

在这里插入图片描述
我们可以从这些信息中得到:
在这里插入图片描述

为什么core默认是被关闭的

core文件中有错误的详细信息,为啥默认是关闭的呢?

Core files,默认关闭的主要原因有以下几点:

  1. 安全性考虑:Core文件可能包含敏感信息,如程序运行时的内存数据,这可能包括密码、密钥或是其他重要数据。如果这些信息落入不当之手,可能会造成安全风险。因此,默认关闭可以减少潜在的信息泄露。
  2. 磁盘空间占用:Core文件可能非常大,特别是对于消耗大量内存的应用程序来说。如果不加限制地生成,可能会迅速消耗系统磁盘空间,影响系统的正常运行和其他程序的功能。
  3. 性能考量:频繁生成Core文件会对系统性能产生一定影响,尤其是在高负载或资源紧张的服务器环境中,额外的I/O操作来写入这些大文件可能会成为瓶颈。
  4. 默认保守策略:系统管理员通常倾向于采取较为保守的配置策略,避免不必要的麻烦。只有当特定需求出现时,比如在开发和调试环境中,才会选择性地开启Core文件生成,以便于问题诊断。
  5. 用户意识:不是所有用户都了解如何正确地使用和分析Core文件,对于非技术用户来说,这些文件可能是无用且占空间的。因此,默认关闭可以避免给普通用户带来困惑。

尽管如此,对于开发者和系统管理员来说,Core文件是一个强大的调试工具,能够在程序崩溃时提供宝贵的诊断信息。因此,在开发和测试环境中,通常会根据需要配置开启Core文件生成,并合理设定其大小和存放位置,以平衡调试便利性和系统管理的需求。

阻塞信号

信号其他相关常见概念

实际执行信号的处理动作称为信号递达(Delivery)
信号从产生到递达之间的状态,称为信号未决(Pending)
进程可以选择阻塞 (Block )某个信号
被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作

这里我们来介绍一下信号递达和信号未决

信号递达

信号递达(Signal Delivery)指的是操作系统将一个已产生的信号正式通知给目标进程的过程。当一个信号被发送给一个进程,操作系统负责确保这个信号最终被该进程知晓并采取相应的行动。这一过程包括几个关键步骤:

  1. 信号产生:信号可能由硬件异常(如除零错误)、软件请求(如通过kill系统调用)、终端输入(如Ctrl+C)或其他进程操作产生。
  2. 检查信号屏蔽:在信号尝试递达之前,操作系统会检查目标进程的信号屏蔽字(signal mask)。如果该信号被进程阻塞(即包含在信号屏蔽字中),则信号不会立即递达,而是保持未决状态,直到进程解除对该信号的阻塞。
  3. 安排递达:如果信号未被阻塞,操作系统会选择合适的时机将信号递交给进程。这个时机通常是进程当前指令执行完毕,或者在某些可中断点。
  4. 处理信号:信号递达后,进程可以选择如何响应:
  • 默认动作:如果没有为信号安装自定义的处理函数,操作系统会执行该信号的默认动作,比如终止进程(如SIGINT, Ctrl+C)、忽略(如SIGCHLD)或暂停进程(如SIGSTOP)。
  • 自定义处理函数:如果进程之前通过sigactionsignal系统调用注册了信号处理器,则当信号递达时,会调用该处理器函数。在信号处理函数执行期间,可能会有其他信号的递达被临时阻塞,以避免并发处理信号导致的复杂情况。
  1. 信号处理完成:信号处理结束后,进程恢复正常的执行流程,除非信号导致了进程终止或产生了其他不可逆的状态变化。

信号递达机制是操作系统提供的一种进程间通信和异常处理的方式,对于编写健壮的、能够优雅处理外部事件的程序至关重要。

信号未决

信号未决(Signal Pending)是指在计算机操作系统中,尤其是Linux系统环境下,一个信号已经产生但尚未被进程处理的状态。当一个信号被发送给一个进程,但该进程目前因为某些原因不能立即处理这个信号时,这个信号就会处于未决状态。

信号未决主要发生在以下几种情况:

  1. 信号阻塞:进程通过设置信号屏蔽字(signal mask)来阻塞某些信号。当被阻塞的信号产生时,它不会立即被递送到进程,而是保持在未决状态,直到进程解除对该信号的阻塞。
  2. 信号处理:如果进程正在处理另一个信号,新产生的信号可能会等待当前信号处理完成后再进行处理,这时新信号也是未决的。
  3. 特定时机:在某些特定执行点,如系统调用的不可中断点,即使信号没有被显式阻塞,也可能暂时保持未决状态,直到该操作完成。

信号未决状态是暂时的,它确保了信号在适当的时候被处理,而不是在进程执行某些关键操作时打断进程,从而保护了程序的稳定性和数据的一致性。进程可以通过调用如sigpending这样的系统调用来查询当前有哪些信号处于未决状态。

简单点来说阻塞的意思就是一直让信号处于未决状态
下面我们来介绍信号阻塞:

信号阻塞

信号阻塞是操作系统中一种管理信号(signals)的机制,尤其在Unix和类Unix系统如Linux中较为常见。这一机制允许进程暂时阻止(或“屏蔽”)某些信号的递达,直到进程准备好处理它们。以下是信号阻塞概念的核心要点:

  1. 信号(Signals):信号是操作系统用来通知进程发生了某种事件的机制。这些事件可能包括用户请求终止进程(如Ctrl+C产生的SIGINT)、硬件异常、软件条件(如除零错误)等。
  2. 信号屏蔽字(Signal Mask):每个进程都有一个信号屏蔽字,这是一个数据结构,通常是一个位图,其中每个位对应一个可能的信号。如果某个信号对应的位被设置(通常是1),则表示该信号当前被阻塞,即系统不会立即将该信号递交给进程处理。
  3. 阻塞行为:当一个被阻塞的信号产生时,它不会立即影响进程的执行。相反,该信号进入一个“未决状态”,等待进程解除对它的阻塞。这意味着进程可以继续执行而不受该信号的即时干扰,直到它准备好处理这些信号。
  4. 解除阻塞:进程可以通过调用如sigprocmask的系统调用来修改其信号屏蔽字,从而解除对某些信号的阻塞。一旦解除阻塞,任何处于未决状态的相应信号将立即或按先进先出的顺序递达给进程进行处理。
  5. 与信号忽略和默认处理的区别
  • 忽略:如果进程配置了忽略某个信号,那么即使信号未被阻塞,当信号到达时也会被直接丢弃,不会有任何处理动作。
  • 阻塞:信号被阻塞时,它不会被立即处理,而是等待解除阻塞后再递达。
  1. 应用场景:信号阻塞常用于保护关键代码段,确保在执行某些不允许被中断的操作(如资源锁定、数据结构更新等)时,不会因为外部信号的干扰而引发错误或不一致的状态。

综上所述,信号阻塞是进程控制信号处理时机的一种策略,有助于提高程序的稳定性和可靠性。

两者的区别

信号阻塞和信号未决是信号处理机制中的两个关键概念,它们在Linux和其他类Unix系统中扮演着重要角色,但代表了不同的状态和操作:

信号阻塞(Signal Blocking):

  • 定义: 信号阻塞是一种主动的控制机制,通过设置进程的信号屏蔽字(通常使用sigprocmask函数),使得某些信号在产生后不会立即递交给进程进行处理。这相当于为进程设置了一个过滤器,暂时搁置特定信号的处理。
  • 作用: 主要用于保护关键代码段,防止信号中断导致的不一致性或错误。例如,在进行文件系统操作或资源锁的管理时,避免因信号中断而导致数据损坏或死锁。
  • 状态: 信号阻塞是一个动态的开关动作,可以随时开启或关闭。当信号被阻塞时,它仍然可以被内核生成,但不会送达进程,直到解除阻塞。

信号未决(Signal Pending):

  • 定义: 信号未决是一种状态描述,指的是一个或多个信号已经生成但尚未被进程处理的情况。当信号由于阻塞或其他原因(如正在处理另一个信号)不能立即递达时,就会处于未决状态。
  • 作用: 表明有信号等待处理,一旦进程准备好(比如从信号阻塞状态恢复),这些未决信号将会被依次递达并执行相应的处理动作。
  • 状态: 信号未决是一个中间状态,反映了信号从生成到实际处理之间的时间差。信号未决状态由内核维护,并且对于用户空间进程来说通常是透明的,尽管可以通过如sigpending系统调用来查询当前进程的未决信号集。

总结:

信号阻塞是一种预防措施用于控制何时允许信号影响进程,而信号未决描述的是信号已经被生成但还未被进程实际处理的情景信号阻塞导致信号进入未决状态,解除阻塞后,未决信号会被递达处理。这两个概念共同构成了信号处理机制中关于信号何时及如何被响应的核心逻辑。

信号的结构

加上了阻塞之后,我们信号大致就分为三个板块:

  1. 是否阻塞
  2. 是否未决
  3. 信号
    在这里插入图片描述

对于阻塞和未决我们还有几点要注意:

  1. 未决不一定会阻塞(可能只是单纯的没时间处理)
  2. 阻塞一定未决(阻塞的精髓在于根本就没收到信号)
  3. 忽略不是阻塞(忽略是接收到信号之后所做的决定,而阻塞是根本没收到信号)

信号集操作函数

信号集操作函数在Linux系统编程中用于管理和处理进程接收到的信号。这些函数允许程序注册对特定信号的处理方式、屏蔽(阻止)或解除屏蔽某些信号,以及查询信号的当前状态。以下是几个常用信号集操作函数的简要说明:

  1. sigemptyset, sigfillset, sigaddset, sigdelset, sigismember:
  • sigemptyset(sigset_t *set): 初始化信号集set,清空所有信号位,使得信号集不包含任何信号。
  • sigfillset(sigset_t *set): 将信号集set中的所有信号位设置为1,意味着信号集包含所有可能的信号。
  • sigaddset(sigset_t *set, int signum): 向信号集set中添加指定的信号signum
  • sigdelset(sigset_t *set, int signum): 从信号集set中移除指定的信号signum
  • sigismember(const sigset_t *set, int signum): 检查信号signum是否在信号集set中,如果是返回非0值,否则返回0。
  1. sigprocmask:
  • int sigprocmask(int how, const sigset_t *set, sigset_t *oldset): 用于改变当前进程的信号屏蔽字。how参数指定了操作方式(SIG_BLOCK, SIG_UNBLOCK, 或SIG_SETMASK),set指定了新的信号屏蔽字,oldset(如果非NULL)用来保存之前的信号屏蔽字。
    在这里插入图片描述
  1. sigpending:
  • int sigpending(sigset_t *set): 查询当前进程的未决信号集,即将要递达给进程但因被阻塞而暂未处理的信号。结果保存在set指向的信号集中。
  1. sigaction:
  • int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact): 更高级的信号处理函数,用于改变进程对指定信号signum的行为。act指定了新的信号处理动作,oldact(如果非NULL)用于保存先前的信号处理动作。

这些函数允许程序以细粒度控制对信号的响应,增强了程序处理异步事件的能力和灵活性。在多线程环境中,可能还需要考虑使用线程特定的信号掩码函数,如pthread_sigmask

一个简单使用例子

下面的这段代码阻塞了2号信号,从表面来看好像从没接受到一样:

int main()
{sigset_t set,oset;  //信号集//初始化信号集sigemptyset(&set); //最新信号集sigemptyset(&oset); //老信号集//向当前进程的信号集添加信号sigaddset(&set,SIGINT);//设置阻塞sigprocmask(SIG_BLOCK,&set,&oset); //向set设置阻塞信号,在这之前,备份到oset中while(true){std::cout << "process is running... pid :" << getpid() << std::endl; sleep(1);}}

在这里插入图片描述
为了表明确实阻塞了,我们可以设计一个计数器,等到计数器为5时,解除阻塞:

void signal_handler(int signum)
{std::cout << "signum: "<< signum << std::endl;//exit(0);
}int main()
{signal(2,signal_handler); //设置自定义行为sigset_t set,oset;  //信号集//初始化信号集sigemptyset(&set); //最新信号集sigemptyset(&oset); //老信号集//向当前进程的信号集添加信号sigaddset(&set,SIGINT);//设置阻塞sigprocmask(SIG_BLOCK,&set,&oset); //向set设置阻塞信号,在这之前,备份到oset中int cnt = 0;while(true){std::cout << "process is running... pid :" << getpid() << std::endl; if(cnt == 5){sigprocmask(SIG_UNBLOCK,&set,&oset); //解除阻塞信号kill(getpid(),2);}cnt++;sleep(1);}}

在这里插入图片描述

sigpending的使用例子

sigpending的作用是查看当前的信号是否还是在阻塞状态,是为1,不是为0。下面这个例子我们先阻塞2号信号5秒,然后解除2号信号,看相应的位数变化:

#include<iostream>
#include<signal.h>
#include <unistd.h>
#include <stdlib.h>// 信号处理函数
void signal_handler(int signum)
{std::cout << "signum: "<< signum<< std::endl;//exit(0);
}// 打印信号集中的信号
void PrintSign(const sigset_t &pending)
{for(int i = 1 ; i <= 31 ; i++){if(sigismember(&pending,i)){std::cout << "1";}else{std::cout<<"0";}}std::cout<<"\n";
}int main()
{// 设置自定义信号处理函数signal(2,signal_handler);sigset_t set,oset;  // 信号集// 初始化信号集sigemptyset(&set); // 最新信号集sigemptyset(&oset); // 老信号集// 向当前进程的信号集添加信号sigaddset(&set,SIGINT);// 设置阻塞信号sigprocmask(SIG_BLOCK,&set,&oset); // 向set设置阻塞信号,在这之前,备份到oset中int cnt = 0;sigset_t pending;while(true){if(cnt == 5){// 解除阻塞信号sigprocmask(SIG_UNBLOCK,&set,&oset);// 发送信号kill(getpid(),2);}cnt++;// 发送信号kill(getpid(),2);// 获取当前进程的挂起信号集sigpending(&pending);// 打印信号集中的信号PrintSign(pending);// 暂停1秒sleep(1);}}

在这里插入图片描述

这段代码主要演示了如何使用信号处理函数、信号集和信号阻塞。程序中设置了一个自定义的信号处理函数signal_handler,当接收到信号2时,会调用该函数。在main函数中,首先初始化信号集,然后向信号集中添加信号SIGINT。接着,使用sigprocmask函数设置阻塞信号。在循环中,当cnt等于5时,解除阻塞信号并发送信号2。在每次循环中,发送信号2,获取当前进程的挂起信号集,并打印信号集中的信号。最后,暂停1秒。

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

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

相关文章

Linux网络-PXE高效批量网络装机(命令+截图详细版)

目录 一.部署PXE远程安装服务 1.PXE概述 1.1.PXE批量部署的优点 1.2.要搭建PXE网络体系的前提条件 2.搭建PXE远程安装服务器 2.1.修改相关网络配置&#xff08;仅主机模式&#xff09; 2.2.关闭防火墙&#xff08;老规矩&#xff09; 2.3.保证挂载上 2.4.准备好配置文…

呆滞物料规范管理了,问题就好办了

对于制造企业来说&#xff0c;库存是生存和发展的重要保障&#xff0c;过高的库存会占用企业大量的资金和管理成本&#xff0c;影响企业的正常生产&#xff0c;然而多数中小制造企业还在用人工干预管理&#xff0c;如何控制呆滞物料成为仓储管理的一大难题。 什么是呆滞料 呆滞…

为什么不建议在 Vue <style> 中使用 scoped?

前言 亲爱的小伙伴&#xff0c;你好&#xff01;我是 嘟老板。我们使用 Vue 开发页面时&#xff0c;经常需要在 <style> 标签下编写样式。不知你是否留意&#xff0c;在 <style> 标签下有一个属性经常出现 - scoped。你知道它起到什么作用吗&#xff1f;原理是怎样…

[Java EE] 多线程(九):ReentrantLock,Semaphore,CountDownLatch与线程安全的集合类(多线程完结)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

PE文件(四)FileBuffer-ImageBuffer作业

C语言实现如下功能 2.编写一个函数&#xff0c;将RVA的值转换成FOA 将文件加载到内存时&#xff0c;已知一个数据在内存中的地址&#xff0c;将此地址转化成文件在硬盘上时的相对于文件起始地址的文件偏移地址。即将虚拟内存偏移地址转换成文件偏移地址。 说明&#xff1a;这里…

记一次DNS故障导致用户无法充值的问题(上)

背景&#xff1a; 刚刚过去了五一劳动节&#xff0c;回来后一上班接到客服运营团队反馈的节日期间的问题&#xff0c;反馈有部分用户无法充值。拿到的反馈资料有&#xff1a; 无法充值操作视频、问题时间、手机机型、手机网络情况。 1、从视频中看到用户点击支付后没有任何反…

Linux系统使用Docker安装青龙面板并实现远程访问管理面板

文章目录 一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 青龙…

聊聊 ASP.NET Core 中间件(三):如何创建自己的中间件?

前言 本质上&#xff0c;中间件类也是一个普通的 .NET 类&#xff0c;它不需要继承任何父类或者实现任何接口。 但是有几个约定&#xff1a; 需要有一个构造方法构造方法至少要有一个 RequestDelegate 类型的参数&#xff0c;用来指向下一个中间件。需要定义一个名字为 Invo…

嵌入式linux学习第一天

参考正点原子Linux开发文档。记录下知识点。 Shell 基本操作 前面我们说 Shell 就是“敲命令”&#xff0c;那么既然是命令&#xff0c;那肯定是有格式的&#xff0c;Shell 命令的格式 如下&#xff1a; command -options [argument] command: Shell 命令名称。 options&…

雷军-2022.8小米创业思考-6-互联网七字诀之专注:有所为,有所不为;克制贪婪,少就是多;一次解决一个最迫切的需求

第六章 互联网七字诀 专注、极致、口碑、快&#xff0c;这就是我总结的互联网七字诀&#xff0c;也是我对互联网思维的高度概括。 专注 从商业角度看&#xff0c;专注就是要“把鸡蛋尽量放在一个篮子里”。这听起来似乎有些不合理&#xff0c;大家的第一反应可能是“风险会不会…

JUC-synchronized练习-交替打印ABC

今天来练习一下synchronized 简单来利用synchronized实现一个字符串的交替打印 主要的实现设置一个全局的变量state&#xff0c;线程执行通过不断累加state&#xff0c;根据state对三取余的结果来判断该线程是否继续执行还是进入等待。并通过synchronized锁住一个共享变量loc…

js 图片渐变

1. 点击图片&#xff0c;使其渐变为另一张图片 通过定义keyframes来创建一个淡入淡出的动画效果。当图片被点击时&#xff0c;先添加淡出动画使图片透明度从0渐变到1&#xff0c;然后在1秒后切换图片源并添加淡入动画使新图片透明度从0渐变到1&#xff0c;实现图片渐变效果。 …

自动化机器学习——贝叶斯优化

自动化机器学习——贝叶斯优化 贝叶斯优化是一种通过贝叶斯公式推断出目标函数的后验概率分布&#xff0c;从而在优化过程中不断地利用已有信息来寻找最优解的方法。在贝叶斯优化中&#xff0c;有两个关键步骤&#xff1a;统一建模和获得函数的优化。 1. 统一建模 在贝叶斯优…

.双链表.

题目&#xff1a; 实现一个双链表&#xff0c;双链表初始为空&#xff0c;支持 55 种操作&#xff1a; 在最左侧插入一个数&#xff1b;在最右侧插入一个数&#xff1b;将第 k&#x1d458; 个插入的数删除&#xff1b;在第 k&#x1d458; 个插入的数左侧插入一个数&#xf…

新型中医揿针如何降血糖呢?

点击文末领取揿针的视频教程跟直播讲解 “新型针贴”专用揿针是为“埋针疗法”特制治的一种特殊针具&#xff0c;它是古代针刺留针方法的发展。具体来说&#xff0c;它是将特制针具刺入皮内&#xff0c;固定后留置一定时间&#xff0c;利用其持续微弱的刺激作用来治疗疾病的一…

做抖音小店需要注意什么?这几点很多人不知道,看完防踩坑

大家好&#xff0c;我是电商笨笨熊 抖音小店虽然推出了一段时间&#xff0c;但是依旧有新手玩家陆陆续续加入其中&#xff1b; 对于很多新手来说&#xff0c;只看到了其中红利&#xff0c;但却没有看到其中包含的一些运营小细节&#xff0c;且这些细节决定你店铺未来发展&…

【redis】Redis数据类型(四)Set类型

目录 Set类型介绍使用场景 Set类型数据结构set的单个元素的添加过程IntSet哈希表内存结构 常用命令SADD示例 SREM示例 SMEMBERS示例 SISMEMBER示例 SCARD示例 SMOVE示例 SPOP示例 SRANDMEMBER示例 SINTER示例 SINTERSTORE示例 SUNION示例 SUNIONSTORE示例 SDIFF示例 SDIFFSTORE…

每日一题(PTAL2):列车调度--贪心+二分

选择去维护一个最小区间 代码1&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n;cin>>n;int num;vector <int> v;int res0;for(int i0;i<n;i){cin>>num;int locv.size();int left0;int rightv.size()-1;while(left<…

Go语言fmt包深度探索:格式化输入输出的利器

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f3ad; 引言一、基础输出函数fmt.Print与fmt.Println&#x1f4cc; fmt.Print&#xff1a;纯粹输出&#xff0c;不带换行&#x1f4cc; fmt.Println&#xff1a;输出后自动添加换行符 二、格式化输出fmt.Printf&…

在Java中如何有效地处理内存泄露

在Java中&#xff0c;处理内存泄露有多种方法&#xff0c;以下是其中三种常见的方法及其原理和适用场景&#xff1a; ## 1. 合理使用垃圾回收机制 Java中的垃圾回收机制&#xff08;Garbage Collection&#xff0c;GC&#xff09;是一种自动化的内存管理技术&#xff0c;它可以…