1.一台客户端有三百个客户与三百个客户端有三百个客户对服务器施压,有什么区别?

一个客户端,三百个用户

只有一个客户端,三百个用户肯定不能同时进行操作,假设每次一人操作客户端对服务器施压,服务器承受的压力小但持续时间长。所有用户在一个客户端上,不必考虑分布式管理的问题。一个客户端三百个用户会占用客户机更多的资源,而影响测试的结果。线程之间可能发生干扰,而产生一些异常。而三百个用户的数据都在同一客户端,连接数显著减少,意味着需要更大的带宽来传输这些数据

三百个客户端,三百个用户

假设三百个客户端同时进行操作对服务器施压,就要求服务器带宽能够承受三百人同时在线操作,且服务器短时间内承受压力大但持续时间短。用户分布在不同的客户端上,需要考虑使用控制器来整体调配不同客户机上的用户。同时,还需要给予相应的权限配置和防火墙设置。单个客户端只传送各自有限的信息,数据量是不大的,还可以错开时间传输。

问题总结:

1)资源方面:200个客户在1台客户端会占用很多资源

2)线程方面:200个客户在1台客户端会产生线程干扰

3)带宽方面:200个客户在1台客户端需要更大的带宽

4)ip地址问题:服务器对于单一IP地址最大连接数的限制(可以使用IP Spoof绕过)

5)分布式管理:200个客户在1台客户端不用考虑,另一种方式则需要考虑使用控制器来整体调配不同客户机上的用户

6)权限和防火墙设置:200个客户端有200个客户需要考虑这个问题

到底什么叫分布式?

所谓分布式,无非就是”将一个系统拆分成多个子系统并散布到不同设备“的过程而已。拆分+连接是分布式系统的本质

本质上而言,实现一个分布式系统,最核心的部分无非有两点:

  1. 如何拆分——可以有很多方式,核心依据一是业务需求,二是成本限制。这是实践中构建分布式系统时最主要的设计依据。
  2. 如何连接——光把系统拆开成 Process 还不够,关键是拆开后的 Process 之间还要能通信,因此涉及通信协议设计的问题,需要考虑的因素很多,好消息是这部分其实成熟方案很多

只要遵循下述步骤即可将任何一个软件拆分为“分布式”的:

  1. 将你的整个软件视为一个系统(不管它有多复杂)
  2. 将整个系统分割为一系列的 Process(进程), 每个 Process 完成一定的功能
  3. 将这些 Process 分散到不同的机器上。分散后,选择若干种(没错一种可能不够)通信协议把他们连接起来

2. 关于C++中的友元函数说法正确的是

  1. 友元函数需要通过对象或指针调用?
    友元函数的调用类似普通函数,直接调用
  2. 友元函数没有this指针?
    是的
  3. 友元函数破环了继承性机制
    不是,破坏的是封装机制
  4. 友元函数是不能被继承的
    是的

友元函数的简单介绍:

如果类A中的函数或者一个普通函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数或者普通函数要是类B的友元函数,通过这种方式,允许外面的类或函数去访问类的私有变量和保护变量。这样做的好处在于:能够提高效率,表达简单、清晰。但是也有缺点:友元函数破环了封装机制,将私有变量或者保护变量暴露在外。

具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元。(2)两个类要共享数据的时候。

友元函数的调用类似普通函数,可以直接调用友元函数,不需要通过对象或指针,即友元函数没有this指针。且因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且没有区别。

因为友元函数没有this指针,则参数要有三种情况:

2.1.1 要访问非static成员时,需要对象做参数;

2.1.2 要访问static成员或全局变量时,则不需要对象做参数;

2.1.3 如果作为参数的对象是全局对象,则不需要对象做参数;

需要特别注意:友元函数没有this指针!友元函数不能被继承

3.下列不是B/S模式优点的一项是()?

  1. 分布性强,客户端零维护,只要有网络、浏览器,就可以随时随地进行查询、浏览等业务处理。(√)
  2. 维护简单方便,只需要改变网页,即可实现所有用户的同步更新(√)
  3. 业务扩展简单方便,通过增加网页即可增加服务器功能(√)
  4. 容易保证安全性,程序更注重流程(×)

B/S模式举例:在线计算器、在线P图这些网站,核心部分集中到服务器上,客户通过浏览器(Browse)运行软件
C/S模式举例:各种需要装客户端的网游,界面表示、事务处理逻辑放在客户端,服务端主要负责数据的存储管理,这就是胖客户端模式。

B/S模式及其优缺点简介

即Browser/Server(浏览器/服务器)结构,就是只安装维护一个服务器(Server),而客户端选用浏览器(Browse)运行软件。这种模式将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。只需要安装一个浏览器和数据库,就可以让浏览器通过Web Server同数据库进行数据交互。

界面显示逻辑放在浏览器,事务处理逻辑则在Web Server。极少数的逻辑在前端实现,但主要的事务逻辑在服务器端实现。通常由Browser、Web Server、数据存储Server形成三层架构。

B/S模式的优点

  1. 分布性强,客户端零维护,只要有网络、浏览器,就可以随时随地进行查询、浏览等业务处理。
  2. 维护简单方便,只需要改变网页,即可实现所有用户的同步更新
  3. 业务扩展简单方便,通过增加网页即可增加服务器功能
  4. 开发简单,共享性强。有大量的第三方B/S组件和技术,可用于后端开发、前端显示,因此从快速开发角度来看BS模式占有很大的优势。

B/S模式的缺点

  1. 个性化特点明显降低,无法实现具有个性化的功能要求:集成诸如指纹仪、摄像头、调用播放器变得困难。虽然IE浏览器支持ActiveX扩展,但是在兼容性等方面又不尽如人意。

  2. 在跨浏览器上,BS架构不尽如人意:尤其是在对HTML5的支持上,各主流浏览器都存在或多或少的差异,但随着时间的推移,这种情况将会有很大的改观。

  3. 请求/响应模式带来的性能问题:为了提高使用体验,通常会采用动态刷新网页的方式,给服务器带来一定的压力(通过Ajax和WebSocket在一定程度上可以缓解这方面的问题)。
    浏览器一般只负责界面表示,因此一些业务逻辑必须在服务器上完成,像异常情况处理、数据转换、操作日志等。

  4. 无状态方式下的会话控制成本:服务器端在保存数据的同时还要保存用户的状态,开发人员要精心设计提交的次序即信息的完整性,而对C/S而言只需要全部完成后提交即可。

  5. 在速度和安全性上需要花费巨大的设计成本因为所有的操作是通过请求/响应模式工作,弱安全设计不到位,通过简单修改URL参数、篡改POST字段值就会产生安全性方面的问题

  6. 功能弱化,难以实现传统模式下的特殊功能要求:浏览器作为界面展示的平台和脚本语言的执行环境,它无法超越浏览器所能支持的功能特性。ActiveX、Flash、Java Servlet都是为了扩展功能曾经使用的技术,但是因为兼容性、安全性等方面的问题,已经基本被淘汰。

C/S模式及其优缺点简介

C/S(Client/Server):客户端/服务器结构。界面表示、事务处理逻辑放在客户端,服务端主要负责数据的存储管理,这就是胖客户端模式。而在三层架构模式下,表示层和少量的事务处理放在客户端,主要的事务处理逻辑放在业务应用服务端,同时数据存储管理仍然为独立的一层。

C/S模式的优点

  1. 能充分发挥客户端PC的处理能力: 很多工作可以在客户端处理后在提交给服务器,因此CS客户端的响应速度快。客户端应用可以利用工作终端的多核CPU、内存、GPU等硬件资源。像AutoCAD、Photoshop、游戏软件客户端等,还会针对显卡进行特殊优化。
  2. 操作界面漂亮、形式多样,可以充分满足客户自身的个性化要求: 客户端应用的自主性更强,客观的讲,浏览器自身就是一个客户端应用。客户端应用可以集成第三方软硬件,例如指纹仪、智能卡、加密狗等
  3. CS结构的管理信息系统具有较强的事务处理能力,能实现复杂的业务流程
  4. 容易保证安全性,程序更注重流程: C/S一般面向相对固定的用户群,可以对权限进行多层次检验,提供了更安全的存取模式。一般高度机密的信息系统采用C/S结构为宜。

C/S模式的缺点

  1. 需要专门的客户端安装程序,分布功能弱,快速部署安装和配置困难
  2. 兼容性差,需要考虑运行平台,如操作系统版本: 针对不同的平台,需要使用不同的开发工具开发。操作系统版本(win 7/win 10/Linux)、系统类型(x86/x64)。
    尽管一些中间语言,如java、.net通过虚拟机可以解决运行平台的差异性,但涉及到Native相关的组件,仍然需要考虑平台差异性,典型的如各种解码器,第三方组件需要区分x86和x64版本。
  3. 开发、维护成本较高,需要具有一定专业水准的技术人员才能完成
    发生一次升级,则所有客户端的程序都需要更新。
    与客户端的形式多样、可以满足客户个性化要求相对应的就是对开发人员的要求也比较高。
  4. 用户群固定,适用面窄
    通常不适合面向一些不可知的用户,因此适用面窄,通常用于局域网。

C/S模式与B/S模式对比

综合对比发现,B/S架构胜在开发相对简单,维护简单方便;而C/S架构胜在性能高自主性强。在这些方面,短期内各自占据着独有的优势。

4. 判断输出题

JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?

public class Test {public static void main(String[] args) {System.out.println(Test2.a);}}
class Test2{public static final String a=new String("JD");static {System.out.print("OK");}}

分析
输出 OKJD

参考类加载及初始化顺序例题

5. 小顶堆

已知小顶堆:{51,32,73,23,42,62,99,14,24,3943,58,65,80,120},请问62对应节点的左子节点是?

6. 输出结果

下列代码执行后的输出结果为( )

int main()
{char c, s[20];strcpy(s, "Hello,World");printf("s[]=%6.9s\n", s);return 0;
}

考察的是%6.9s代表的含义,它表示显示一个长度不小于6且不大于9的字符串。若大于9,则第9个字符以后的内容将被删除

输出域宽

控制符:

%d 十进制有符号整数;%u 十进制无符号整数;%f 浮点数
%e 指数形式的浮点数;%ld 长整型;%lf 长型浮点数
%x 十六进制;%o 八进制;%c 字符
%s 字符串;%p 指针的值;%g 自动选择合适的表示法

在%和字母之间插入数字表示最大场宽

%3d 表示输出3个整数,不够3位右对齐
%04d 表示在输出一个小于4位的数值时,讲在前面补0使其总宽度为4位
%-7d 表示输出7位整数左对齐
%9.2f 表示输出场宽为9的浮点数,其中小数位为2,整数位为6,小数点占一位,不够9位右对齐
%8s 表示输出8个字符的字符串,不够8个字符右对齐
%6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9,则第9个字符以后的内容将被删 除
%-10s 表示输出10个字符左对齐

7. 判断输出题

继承是JAVA语言的一个特性,针对类的继承,虚拟机会如何进行父类和子类的初始化加载呢?请阅读代码选择出该段代码的输入结果。

public class Test {public static void main(String[] args) {System.out.print(B.c);}
}class A {static {System.out.print("A");}
}class B extends A{static {System.out.print("B");}public final static String c = "C";
}

试卷中会有两道类似的题目(代码部分略有不同),请同学务必仔细阅读上述代码,再作答
输出C
参考类加载及初始化顺序例题

8.采用哪种遍历方法可唯一确定一棵二叉树?( )

唯一确定一棵二叉树主要有两种方式:

  1. 二叉树的先序遍历+中序遍历
  2. 二叉树的后序遍历+中序遍历

先序遍历或者后序遍历用于确定根节点,中序遍历用于划分左右子树,通过两种遍历结果来不断递归地确定根结点和划分左右子树,最终可以确定唯一一棵二叉树,举例如下:

如果不给定中序遍历,只给定先序和后序遍历,无法确定左右子树的划分,也就无法唯一确定一棵二叉树。

现假设存在一棵二叉树,其先序、中序和后序遍历的结果如下:
先序遍历:ABDEGCFH
中序遍历:DBGEACFH
后序遍历:DGEBHFCA

1. 先序遍历+中序遍历:

利用先序遍历确定根结点,再利用中序遍历划分左右子树

  1. 先序遍历,其遍历方式是中左右,故先序遍历结果中的第一个元素一定是根结点,根据上述先序遍历可以知道是A。接着利用得到的A,在中序遍历结果中找到A所在的位置,然后便可以将A左侧的所有元素归属到根结点的左子树,A右侧的所有元素归属到根结点的右子树,而之所以这样做,是因为对于中序遍历,其遍历方式是左中右。
  2. 在以同样方式分析A的左子树,从先序遍历和中序遍历的结果提取出:
    部分先序遍历:BDEG
    部分中序遍历:DBGE
    同样步骤得到

    ……
    走完这个重复的流程,唯一确定二叉树:

2. 后序遍历+中序遍历

利用后序遍历确定根结点,再利用中序遍历划分左右子树,方法与先序遍历+中序遍历唯一确定一棵二叉树的方法本质上是一样的,唯一不同在于,利用后序遍历+中序遍历唯一确定一棵二叉树的方法在每次确定根结点时,需要对后序遍历的结果从后往前看,比如对于上述例子中的后序遍历:DGEBHFCA,第一步确定根结点时,需要取最后一个元素,因为后序遍历是最后才访问根结点,所以此时根结点的位置就是最后一个,而其他步骤就与先序遍历+中序遍历唯一确定一棵二叉树的方法是一样的了。

9. 判断输出题

public class Main {private static int x = 10;private static Integer y = 10;public static void updateX(int value) {value = 3 * value;}public static void updateY(Integer value) {value = 3 * value;}public static void main(String[] args) {updateX(x);updateY(y);}
}

执行以上程序后,x和y的值分别是多少?
答案:10,10

10.不同的linux 操作系统安装方式

公司网络中心有的服务器不配备光驱,有的服务器USB端口损坏,网络管理员根据不同的环境可以使用不同的linux 操作系统安装方式,一般支持以下方式( )

  1. NFS
  2. CDROM
  3. TFTP
  4. Hard drive

安装Linux共有五种方法

1、光盘(CDROM)
2、硬盘(Hard drive)
3、NFS映像
4、FTP
5、HTTP
Local CDROM从当前系统光盘安装程序。即使用光盘安装。
Hard drive从当前系统硬盘安装,即安装文件位于当前主机的硬盘驱动器中。
NFS image网络安装,使用网络上的NFS服务器安装,要求NFS服务器拥有系统安装程序。
FTP网络安装,使用网络上的FTP服务器安装,要求FTP服务器拥有系统安装程序。
HTTP网络安装,使用网络上的HTTP服务器安装,要求HTTP服务器拥有系统安装程序。

具体安装方法见:Linux操作系统安装的5种方法以及心得
TFTP(Trivial File Transfer Protocol,简单文件传输协议: 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。不用于linux系统的安装。

11.Ext3日志文件系统的特点是

Ext3日志文件系统来源

Linux缺省情况下使用的文件系统为Ext2,ext2文件系统的确高效稳定。但是,随着Linux系统在关键业务中的应用,Linux文件系统的弱点也渐渐显露出来了:其中系统缺省使用的ext2文件系统是非日志文件系统。这在关键行业的应用是一个致命的弱点。本文向各位介绍Linux下使用ext3日志文件系统应用。
Ext3文件系统是直接从Ext2文件系统发展而来,目前ext3文件系统已经非常稳定可靠。它完全兼容ext2文件系统。用户可以平滑地过渡到一个日志功能健全的文件系统中来。这实际上了也是ext3日志文件系统初始设计的初衷。

Ext3日志文件系统的特点

  1. 高可用性 : 系统使用了ext3文件系统后,即使在非正常关机后,系统也不需要检查文件系统。宕机发生后,恢复ext3文件系统的时间只要数十秒钟。
  2. 数据的完整性: ext3文件系统能够极大地提高文件系统的完整性,避免了意外宕机对文件系统的破坏。在保证数据完整性方面,ext3文件系统有2种模式可供选择。其中之一就是“同时保持文件系统及数据的一致性”模式。采用这种方式,你永远不再会看到由于非正常关机而存储在磁盘上的垃圾文件。
  3. 文件系统的速度: 尽管使用ext3文件系统时,有时在存储数据时可能要多次写数据,但是,从总体上看来,ext3比ext2的性能还要好一些。这是因为ext3的日志功能对磁盘的驱动器读写头进行了优化。所以,文件系统的读写性能较之Ext2文件系统并来说,性能并没有降低。
  4. 数据转换 :由ext2文件系统转换成ext3文件系统非常容易,只要简单地键入两条命令即可完成整个转换过程,用户不用花时间备份、恢复、格式化分区等。用一个ext3文件系统提供的小工具tune2fs,它可以将ext2文件系统轻松转换为ext3日志文件系统。另外,ext3文件系统可以不经任何更改,而直接加载成为ext2文件系统。
  5. 多种日志模式 :Ext3有多种日志模式,一种工作模式是对所有的文件数据及metadata(定义文件系统中数据的数据,即数据的数据)进行日志记录(data=journal模式);另一种工作模式则是只对metadata记录日志,而不对数据进行日志记录,也即所谓data=ordered或者data=writeback模式。系统管理人员可以根据系统的实际工作要求,在系统的工作速度与文件数据的一致性之间作出选择。

12. mount命令的使用

网络管理员把优盘上的源代码给程序员参考,但要防止程序误删除或修改,以下正确的加载方式是( )

  1. mount -o defaults /dev/sdb1 /tools
  2. mount -o ro /dev/sdb1 /tools
  3. mount -r /dev/sdb1 /tools
  4. mount -o ro /dev/sdb /tools

考察linux磁盘管理。

mount命令的简单介绍

mount命令是经常会使用到的命令,它用于挂载Linux系统外的文件。任何块设备都不能直接访问,需挂载在目录上访问,挂载即将额外文件系统与根文件系统某现存的目录建立起关联关系,进而使得此目录做为其它文件访问入口的行为(挂载的设备必须有文件系统)

mount [-选项] DEVICE(设备) MOUNT_POINT(挂载点)
挂载选项-
-r:readonly ,只读挂载,不能进行其他操作,和权限无关,介质只能读,多用于冷备份。在mount 查询时时显示 ro
-o options:( 挂载文件系统的选项) ,多个选项使用逗号分隔
-o ro:只读 rw:读写(defaults)
device
指明要挂载的设备① 设备文件:例如/dev/sda5

1.中-o defaults是读写,错误;2.-o ro:只读正确;3.-r相当于-o ro,代表只读,正确;
4.sdb表示整个SD卡设备名,sdb1表示SD卡的第一个分区。相应的,如果还有一个分区的话,表示为sdb2,用fdisk -l命令查看U盘的盘符。 一般为/dev/sdb1。题目说的是U盘中的源代码,所以应该为/dev/sdb1,但是为什么/dev/sdb不行呢?这里不理解。

关于mount命令的具体介绍,此处不再详细展开

/dev 简介

/dev 文件下是设备,/dev/hda, /dev/hdb, /dev/sda, /dev/sdb, 他们之间有什么区别?

答:hda一般是指IDE接口的硬盘,hda指第一块硬盘,hdb指第二块硬盘,等等;sda一般是指SATA接口的硬盘,sda指第一块硬盘,sdb指第二块硬盘,等等。

/dev/sd* 文件

/dev/sd* 文件,此类文件时磁盘设备文件,并不能直接访问磁盘,必须要将磁盘挂载到某一个目录才可以访问。(sd* 表示以sd开头的磁盘文件,如 sda, sda1.sda2.sda5,sdb,sdb1)

如何确定u盘盘符

  1. 查看所有以sd开头的磁盘文件。
  2. 再拔掉u盘,重新cd sd*, 看看少了哪些sd的文件,则说明该u盘就是该文件(注意:u盘对应多个sd开头的文件哦!!)
  3. 如 U盘对应 sdb 和 sdb1; 那么sdb1就是U盘的分区1;如设置多个分区,则分多几个sdbx;通过上述,说明 /dev/sdb 和 /dev/sdb1 是U盘的设备文件(不一定是sdb哦,不同电脑不一样,可能是sdc等等,自己操作就知道是哪个文件了)

所以是不是说明4. mount -o ro /dev/sdb /tools也可行,我不李姐-_-,有知道的朋友麻烦评论区告知一下~

13. 在C++中,引用和指针的区别

  1. 引用总是指向一个对象,指针可能不指向对象(√)
  2. 引用创建时必须初始化,而指针则可以在任何时候被初始化(√)
  3. 引用不能用const修饰,而指针可以(√)
  4. 引用和指针都可以被重新赋值(×)

C++中引用的简介

引用可以看做是数据的一个别名,通过这个别名和原来的名字都能够找到这份数据。引用的定义方式类似于指针,只是用&取代了*,比如int &r = a;r是a的引用。需要区分定义时加&表示引用,使用时加&表示取地址。

引用必须在定义的同时初始化,并且不能再引用其它数据,有点类似于常量(const 变量)。引用 r 和原始变量 a 都是指向同一地址,所以通过引用也可以修改原始变量中所存储的数据,如果不希望通过引用来修改原始的数据,那么可以在定义时添加 const 限制。

C++中引用的本质

引用只是对指针进行了简单的封装,它的底层依然是通过指针实现的,引用占用的内存和指针占用的内存长度一样,在 32 位环境下是 4 个字节,在 64 位环境下是 8 个字节,之所以不能获取引用的地址。例子如下:
写的语句

编译器转换后的语句

(r本身是指针、r 存储的内容是变量地址,&r经过编译器转换实际返回的是r存储的内容)

总结来说引用r 是占用内存的、r 存储的内容是变量地址,之所以使用者认为引用不占用额外的内存,是因为编译器对引用进行了内部转换。虽然是基于指针实现的,但它比指针更加易用,获取数据时不需要加*,和普通变量的使用方式一样

引用和指针的区别

1)引用必须在定义时初始化,并且不能再指向其他数据;而指针没有这个限制,指针在定义时不必赋值,以后也能指向任意数据。
2)可以有 const 指针,但是没有 const 引用,因为指针可以改变指向的对象,但是引用不行,所以没有必要加const。即不能有int & const r = a;
但是可以有int const &r = a,这代表
3)指针可以有多级,但是引用只能有一级,例如,int **p是合法的,而int &&r是不合法的。
4) 指针和引用的自增(++)自减(–)运算意义不一样。对指针使用 ++ 表示指向下一份数据,对引用使用 ++ 表示它所指代的数据本身加 1;自减(–)同样。

14. 判断输出题

有以下程序

#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main()
{ofstream File1("text.txt");string d("20160314");string y = d.substr(0, 4);int k = d.find("2");int i = d.find("3");string m = d.substr(k + 2, i - k);string dd = d.substr(i + 1, 2);string n = dd + m + y;File1 << n << endl;File1.close();
}

文件text.txt中写入的结果是( )

考察的是字符串函数string.substr()和string.find()的用法

substr() 函数
用于从 string 字符串中提取子字符串,它的原型为:
string substr (size_t pos = 0, size_t len = npos) const;
pos 为要提取的子字符串的起始下标,len 为要提取的子字符串的长度。
find() 函数
find() 函数用于在 string 字符串中查找子字符串出现的位置,它其中的两种原型为:
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
第一个参数为待查找的子字符串,它可以是 string 字符串,也可以是C风格的字符串。第二个参数为开始查找的位置(下标);如果不指明,则从第0个字符开始查找。

根据这两个函数定义,稍微推导一下就可以得到答案 14160312016

15. 如何在多线程中避免发生死锁?

  1. 允许进程强行从占有者那里夺取某些资源。(√)
  2. 进程在运行前一次性地向系统申请它所需要的全部资源。(√)
  3. 允许进程同时访问某些资源。(√)
  4. 把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。(√)

此题考查死锁的解决方法

什么是死锁

线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。当线程进入对象的synchronized代码块时,便占有了资源,直到它退出该代码块或者调用wait方法,才释放资源,在此期间,其他线程将不能进入该代码块。当线程互相持有对方所需要的资源时,会互相等待对方释放资源,如果线程都不主动释放所占有的资源,将产生死锁。

死锁的解决方法

死锁的产生是必须要满足一些特定条件的:

  1. 互斥条件:进程对于所分配到的资源具有排它性,即一个资源只能被一个进程占用,直到被该进程释放
  2. 请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用
  4. 循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。

要避免死锁,破坏这些条件即可

  1. 破坏互斥条件:允许进程同时访问某些资源。如果某些资源支持多进程同时访问,就不会产生死锁
  2. 破坏请求和保持条件:进程在运行前一次性地向系统申请它所需要的全部资源。如此进程就不会产生被占用资源而发生阻塞的问题
  3. 破坏不剥夺条件:允许进程强行从占有者那里夺取某些资源。
  4. 破坏循环等待条件:把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。没有环路也就不会循环等待。

产生死锁如何解决

一个可行的做法是释放所有锁,回退,并且等待一段随机的时间后重试。这个和简单的加锁超时类似,不一样的是只有死锁已经发生了才回退,而不会是因为加锁的请求超时了。虽然有回退和等待,但是如果有大量的线程竞争同一批锁,它们还是会重复地死锁(原因同超时类似,不能从根本上减轻竞争)。

一个更好的方案是给这些线程设置优先级,让一个(或几个)线程回退,剩下的线程就像没发生死锁一样继续保持着它们需要的锁。如果赋予这些线程的优先级是固定不变的,同一批线程总是会拥有更高的优先级。为避免这个问题,可以在死锁发生的时候设置随机的优先级。

16.函数指针和指针函数

有以下程序

#include <iostream>
using namespace std;
_______________________
void One(float one)
{cout << "1" << endl;
}
void Two(float two)
{cout << "2" << endl;
}
void Three(float three)
{cout << "3" << endl;
}
int main()
{float i = 1, j = 2, k = 3;function = One;function(i);function = Two;function(j);function = Three;function(k);
}

请为横线处选择合适的程序使得程序的运行结果是123 ( )

  1. void *function();
  2. void *function(float);
  3. void (*function)(float);
  4. void (*function)();

此题考查指针函数和函数指针的区别,以及展示了一个函数指针的使用例子。

指针函数

指针函数是指带指针的函数,即本质是一个函数,函数返回类型是某一类型的指针。当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中。

类型标识符 *函数名(参数表)
int *f(x,y);

首先它是一个函数,只不过这个函数的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。经常使用在返回数组的某一元素地址上。

float *fun();
float *p;
p = fun(a);

函数指针

函数指针是指向函数的指针变量,即本质是一个指针变量。

    int (*f) (int x); /*声明一个函数指针 */f=func; /* 将func函数的首地址赋给指针f */

指向函数的指针包含了函数的地址的入口地址,可以通过它来调用函数。声明格式如下:

类型说明符 (*函数名)   (参数)

其实这里不能称为函数名,应该叫做指针的变量名。这个特殊的指针指向一个返回整型值的函数。指针的声明必须和它指向函数的声明保持一致。
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。

答案:void (*function)(float);
解析:函数指针,且指针的声明必须和它指向函数的声明保持一致。数据类型 (*指针名)(函数参数1,函数参数2,,,)

17.析构函数调用

有以下程序

#include <iostream>
using namespace std;
class D
{int d;
public:D(int x = 1): d(x) {}~D(){cout << "D";}
};
int main()
{D d[] = {_____________};D *p = new D[2];delete[]p;return 0;
}

程序运行的结果是DDDDD,请为横线处选择合适的程序( )

  1. 3,3,3
  2. D(3), D(3), D(3)
  3. D(3,3),D(3,3)
  4. 3,3,3,3

此题考查对象数组,main函数中第二行D *p = new D[2];动态分配了一个 D数组,其中有两个元素,没有指出和参数有关的信息,因此这两个元素都用无参构造函数初始化。
main函数中第二行需要选填,根据选项中四种不同的选填方式

  1. 第一行相当于D d[] = {3,3,3};初始化列表 {3,3,3} 可以看作用来初始化三个数组元素的参数,所以 D[0]、D[1]、D[2] 以 3 为参数,分别调用构造函数进行初始化
  2. 第一行相当于D d[] ={D(3), D(3), D(3)},初始化列表{D(3), D(3), D(3)}可以看作用来初始化三个数组元素的参数,所以 D[0]、D[1]、D[2] 以D(3)为参数,分别调用默认复制构造函数进行初始化

3.4.略
当调用析构函数时,要注意指向动态分配的对象数组的指针需要delete,并在此时调用析构函数。而定义的d[3]会在main函数结尾,即return 0后自动调用析构函数。

18.c++的bool 变量值

对于如下C++程序:

int main() {int a(1), b(3), c(2);while (a < b < c)
{++a;--b;--c;
}cout << a << " " << b << " " << c << "\n";return 0;
}

请问输出结果是()

此题考查c++的bool 变量的值是 1 和 0 表示,而不是 true 或 false

C++定义了一般占用 1 个字节长度的bool 类型,但是在 C++ 中使用 cout 输出 bool 变量的值时还是用数字 1 和 0 表示,而不是 true 或 false。相对的,python、java等语言输出结果为 true 或 false。

题中

  1. 第一次比较a<b(1<3)为真,所以得到1,然后这个1和c比较,1<c(1<2)为真,进入while循环
    得到a=2,b=2,c=1
  2. 第二次比较a<b(2<2)为假,所以得到0,然后这个0和c比较,0<c(0<1)为真,进入while循环
    得到a=3,b=1,c=0
  3. 第三次比较a<b(3<1)为假,得到0,然后这个0和c比较,0<c(0<0)为假,进不去while循环,
    最终结果a=3,b=1,c=0

19.画二叉树

一颗二叉树的叶子节点有5个,出度为1的结点有3个,该二叉树的结点总个数是?
简单题,画一画就成,这里注意出度为1表示只有一个子节点的节点。

20.DELETE和TRUNCATE TABLE的区别

  1. 在删除时如果遇到任何一行违反约束(主要是外键约束),TRUNCATE TABLE仍然删除,只是表的结构及其列、约束、索引等保持不变,但DELETE是直接返回错误(√)
  2. 对于被外键约束的表,不能使用TRUNCATE TABLE,而应该使用不带WHERE语句的DELETE语句。(√)
  3. TRUNCATE TABLE比DELETE的速度快(√)
  4. 如果想保留标识计数值,要用DELETE,因为TRUNCATE TABLE会对新行标志符列使用的计数值重置为该列的种子(√)

DELETE简介

delete 作用是在指定表或者指定视图的基表中删除记录,用户可以删除位于自己模式中的表的记录行,也可以删除表上具有delete权限的记录行,且在删除指定表的记录行时,必须满足该表上的完整性约束条件。delete删除表的所有数据时,不会释放占用的空间,只是在对应位置贴上“可复用”的标签,且操作时可以撤销的。

TRUNCATE简介

truncate用于删除表的所有数据,执行速度快,释放表的占用空间,操作不可撤销。

DELETE和TRUNCATE对比

相同点

truncate和不带where子句的delete, 以及drop都会删除表内的数据

不同点
  1. truncate和 delete只删除数据不删除表的结构(定义)
    drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.
  2. delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
    truncate,drop是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.
  3. delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
    显然drop语句将表所占用的空间全部释放
    truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate会将高水线复位(回到最开始).
  4. 速度,一般来说: drop>; truncate >; delete
  5. 安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及
  6. 在内存中,用delete删除数据,表空间中其被删除数据的表占用的空间还在,便于以后的使用,另外它是“假相”的删除,相当于windows中用delete删除数据是把数据放到回收站中,还可以恢复,当然如果这个时候重新启动系统(OS或者RDBMS),它也就不能恢复了!
    而用truncate清除数据,内存中表空间中其被删除数据的表占用的空间会被立即释放,相当于windows中用shift+delete删除数据,不能够恢复!
使用上

想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
想删除表,当然用drop
想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete.
如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据

21. C++中的抛出异常

对于如下C++程序:


int main() {vector<int> vInt(1);cout << vInt[1];
cout << vInt.at(1);return 0;
}

请问两个cout语句分别会发生什么情况()
选项为抛出异常、未定义两种可能的组合

本题考查的是C++中的抛出异常
C++ 提供了异常(Exception)机制,能够捕获运行时错误,给程序一次“起死回生”的机会,或者至少告诉用户发生了什么再终止程序。所谓抛出异常,就是报告一个运行时错误,程序员可以根据错误信息来进一步处理。

假设用[ ]和string.at()函数处理数组时,两者同时发生下标越界的错误,那么[ ]会返回垃圾值,而string.at()会抛出异常,理由是at() 会检查下标是否越界,如果越界就抛出一个异常;而[ ]不做检查,不管下标是多少都会照常访问。

答案:未定义、抛出异常

22. 友元函数

有以下程序

#include<iostream>
using namespace std;
class complex
{public:int real;int imag;complex(int r = 0, int i = 0){real = r;imag = i;}_________________________________
};
complex add(complex &a, complex &b)
{int r = a.real + b.real;int i = a.imag + b.imag;return complex(r, i);
}
int  main( )
{complex x(1, 2), y(3, 4), z;z = add(x, y);cout << z.real << "+" << z.imag << "i" << endl;
}

程序的输出结果为4+6i,请为横线处选择合适的程序 ( )

考查友元函数,add函数不是complex类的成员函数,所以如果需要在类里声明的话,需要声明为友元函数。

但是,其实这个题目不声明也行,也就是横线的地方可以什么都不填,因为
int real;
int imag;
都是public类成员,不用非得用友元函数来访问,单凭声明的对象引用a和b也能访问到对应的数值

一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员。借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。

注意,友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。

B\C的区别在于B在函数声明时没有给出形参变量名,在c++中,函数形参没有变量名是正常的,没有形参名的函数只用来声明,然而到定义的时候,一般情况下都有形参名称。如果非钻牛角尖,也可以在定义时不给形参名称,但这样的话,函数没啥用,没意义。

23.值类型和引用类型

下面有关值类型和引用类型描述正确的是()?

  1. 引用类型一般都具有继承性,但是值类型一般都是封装的,因此值类型不能作为其他任何类型的基类。(√)
  2. 值类型的变量赋值只是进行数据复制,创建一个同值的新对象,而引用类型变量赋值,仅仅是把对象的引用的指针赋值给变量,使它们共用一个内存地址。(√)
  3. 值类型数据是在栈上分配内存空间,它的变量直接包含变量的实例,使用效率相对较高。而引用类型数据是分配在堆上,引用类型的变量通常包含一个指向实例的指针,变量通过指针来引用实例。(√)
  4. 值类型变量的作用域主要是在栈上分配内存空间内,而引用类型变量作用域主要在分配的堆上。(×)

C++ 应该是没有值类型和引用类型的说法的(或者说不存在与 C# 的引用类型和值类型相对应的概念)

这题 I quit

24.java题

JAVA的类加载期负责整个生命周期内的class的初始化和加载工作,就虚拟机的规范来说,以下代码会输出什么结果?
public class Test {public static void main(String[] args) {System.out.println(Test2.a);}}
class Test2{public static final String a="JD";static {System.out.print("OK");}}试卷中会有三道类似的题目(代码部分略有不同),请同学务必仔细阅读上述代码,再作答

输出JD

25.java题

public class Main {public static void main(String[] args) {System.out.println("A");new Main();new Main();}public Main() {System.out.println("B");}{System.out.println("C");}static {System.out.println("D");}
}
以上程序输出的结果,正确的是?

输出 DACBCB

26. UNION联合体

X定义如下,若存在X a; a.x=0x11223344;则a.y[1]的值可能为( )

union X{int x;char y[4];
};
  1. 44
  2. 11
  3. 22
  4. 33

union是C语言中的一个关键字,它的用法其实与struct很相似。
union中的所有数据成员共用一个空间,同一时间只能存储其中的一个数据成员,并且所有的数据成员有相同的起始地址

小端存储:低地址存低位
大端存储:高地址存低位
大小端存储要以系统而定,小端的话(44332211)应该是33,大端(11223344)的话22

所以答案22和33,需要注意这里11边属于高地址,44边属于低地址。

27.对于京东商城高流量访问,预防Ddos的方法可以有?

  1. 限制同时打开SYN半链接的数目。(√)
  2. 缩短SYN半链接的Time out 时间。(√)
  3. 关闭不必要的服务。(√)
  4. 限制客户端请求服务器时长。(×)

当大量syn请求包发送给服务端的时候,需要设置合理的最大并发半开连接数。一旦超过相应的最大限制,系统就会认为自己收到了syn flood攻击,进入防范模式中。SYN Timeout时间被减短,SYN-ACK的重试次数减少,系统也会自动对缓冲区中的报文进行延时,避免对TCP/IP堆栈造成过大的冲击,力图将攻击危害减到最低。

28.sizeof(struct)对齐的问题

struct Student{
int num;
char name[7];
short age;
char sex;
}student1;
int sz = sizeof(student1);
则执行上面语句后,变量sz的值为( )

直觉上可能觉得sizeof(student1) = sizeof(num) + sizeof(name[7]) + sizeof(age) + sizeof(sex) = 4+ 7 + 2 + 1 = 14;

但是,还有一个对齐的问题需要考虑

结构体大小: 若没有设定对齐字节数,则按基本类型最大成员为对齐字节数。 若有设定对齐字节数,则对齐字节数为 :min(最大成员,设定的对齐字节数)。本题:
num为第一个成员,存放位置0
name[7]存放位置 min(成员自身类型的大小,对齐基数) 为min(1,8),所以是1的整数倍,4
age 存放位置 min(成员自身类型的大小,对齐基数) 为min(2,8) ,所以是12
sex 存放位置 min(成员自身类型的大小,对齐基数) 为min(1,8),所以是14
结构体总大小要求为 min(结构体内最大成员,对齐基数) 为min(4,8),即4的整数倍 0-14是15个字节,要是4的倍数,需要补一个字节,就是16个字节。

简单来讲就是要考虑成员的存放位置必须是 min(成员自身类型的大小,对齐基数) 的倍数,还有结构体总大小必须是min(结构体内最大成员,对齐基数)的倍数这两个条件

结构体内存对齐原则

1.对齐基数; 2.结构体内成员存放位置要求;3.结构体总大小。

  1. 对齐基数部分的说明:1,2,4,8,16称为对齐基数。在没有#pragma pack宏的情况下,一般默认对齐基数为8
  2. 结构体内成员存放位置部分的说明:第一个成员存放在0位置,其余以后的成员存放位置要求为min(成员自身的大小,对齐基数) 的整数倍
  3. 结构体总大小部分的说明:结构体总大小要求为 min(结构体内最大成员,对齐基数) 的整数倍
typedef struct stu
{char c1;  //1int   n;  //4float f;  //4char c2;  //1
}stu;

假设这块为计算机为结构体stu开辟的内存块,设c1存放位置为起始位置,也就是0号位置。

n成员存放位置要满足他自身大小与对齐基数较小者的整数倍的要求.n为int型变量,字节长度为4,4则称之为自身大小,对齐基数为8,较小者为4:

依次类推,最后得到

目前总字节长度为13,结构体总长度计算方式为结构体内部最大成员与对齐基数较小者的整数倍,注意这次是最大成员,显然最大成员为4,4与8比较,较小者为4,因此最接近13的4的整数倍为4的平方,也就是16.

29.

若串S=”UP!UP!JD”,则其子串的数目

这里考察的是子集的概念,这里的串只能由相邻的字符组成,不能任意的搭配,也不能调换次序,这是和集合概念不同的地方
我们把UP!UP!JD 看成是由8个字符组成的字符串
则他的子串:
长度为一:U,P,!,U,P,!,G,D 共8个
长度为二:UP、P!、iU、UP、P!、!J,JD 共7个
长度为三:UP!、P!U、!UP、UP!、P!J, !JD共6个
长度为四:UP!U、P!UP、!UP!、UP!J, P!JD共5个
长度为五:UP!UP、P!UP!J、!UPIJ, UP!JD共4个
长度为六:UP!UP!、P!UP!J, !UP!JD共3个
长度为七:UP!UP!J, P!UP!JD共2个
长度为八:UP!UP!JD共1个
长度为零:空集1个
所以总共有8+7+6+5+4+3+2+1+1=37个子串

也即n(n+1)/2+1 = 8(8+1)/2+1=37(加的1表示空集)

如果不考虑重复,就37了,但是这包含了重复个数,重复的为up、p!、u、 p、 !、 up! 总共6个,37-6=31个

30.C++ STL vector容量(capacity)和大小(size)的区别

对于如下C++程序:

int main() {vector<int> vInt;for (int i=0; i<5; ++i)
{vInt.push_back(i);cout << vInt.capacity() << " ";
}vector<int> vTmp(vInt);
cout << vTmp.capacity() << "\n";return 0;
}

请问程序输出的是()

答案:1 2 4 4 8 5

capacity和size的区别

vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),指的是它实际所包含的元素个数。
对于一个 vector 对象来说,通过该模板类提供的 capacity() 成员函数,可以获得当前容器的容量;通过 size() 成员函数,可以获得容器当前的大小。

capacity在空间已满(2的倍数)的时候,每次增加一倍的空间

举例:

vector v;  //此时没有初始化,所以size()和capacity()都是0;
cout<<v.size()<<endl<<v.capacity()<<endl;
v.push_back(1);
cout<<v.size()<<endl<<v.capacity()<<endl;//此时容器内有一个元素了,那么size()和capacity()都是1
v.push_back(1);
cout<<v.size()<<endl<<v.capacity()<<endl;//此时容器内能够提供的空间capacity()不够用了,需要申请内容,申请多少呢,申请后的大小应该是以前的2倍,那就应该是2了,此时有两个元素,size()为2,capacity()也是2
v.push_back(1);
cout<<v.size()<<endl<<v.capacity()<<endl;//此时容器能够提供的空间是2,又增加元素,不够,需要申请空间,申请后的空间为原来2倍,就是4了,那么size()为3,capacity()为4
v.push_back(1);
cout<<v.size()<<endl<<v.capacity()<<endl;//容器还能够提供一个空间,不需要申请新空间,size()为4,capacity()为4
v.push_back(1);
cout<<v.size()<<endl<<v.capacity()<<endl;//空间不够,需要申请,size()为5,capacity为8

呜呜呜终于结束了……

参考:

【1】一个客户端有三百个用户与三百个客户端有三百个用户对服务器施压,有什么区别?
【2】[网络]1台客户端有200个客户与200个客户端有200个客户对服务器施压的区别
【3】什么是分布式系统(通俗易懂的说法)
【4】应用架构B/S与C/S优劣比较(一)
【5】类加载及初始化顺序例题
【6】唯一确定一个二叉树的方法
【7】在Linux环境中使用Ext3文件系统
【8】mount命令
【9】请查资料了解这些术语:/dev/hda, /dev/hdb, /dev/sda, /dev/sdb, 他们之间有什么区别?…
【10】Linux–Ubuntu入门篇(Ubuntu下的磁盘管理)
【11】什么是死锁?如何避免死锁?
【12】C语言中文网
【13】个人笔经2019校招京东C++
【14】delete和truncate的区别
【15】结构体内存对齐原则
【16】牛客网
【17】c语言中文网

京东C++开发工程师 2019校招卷总结相关推荐

  1. 京东运维开发工程师 2019校招卷总结

    1.echo `expr 3/4`的执行结果 答案3/4 如果是 expr 3 / 4 那么结果将是0 2.range/xrange的区别 range返回值是list,xrange返回值是生成器 生成 ...

  2. 京东C++开发工程师 2020校招卷总结

    1.静态函数 在函数的返回类型前加上static关键字,函数即被定义为静态函数.以下关于静态函数的描述正确的是: B\C明显错误,因为static修饰全局变量或者函数时,主要是为了限制该全局变量或者函 ...

  3. 【计算机就业-后端开发工程师】校招想去互联网公司担任后端开发工程师该怎么准备

    前言 hello大家好,我本次分享的主题是计算机专业校招想去互联网公司担任后端开发工程师该怎么准备,比如说计算机专业投什么岗,笔试面试需要准备什么.我将结合自己以及身边小伙伴们的秋招经历来进行简要的分 ...

  4. 送给即将春秋招的同学--一名服务端开发工程师的校招面经总结

    前言:作为一名21年大学毕业的Java服务端开发工程师,从19年10月份(大三上)开始进行日常实习面试,期间获得小米.快手.领英.Tencent等offer,因疫情爆发无法准时入职,20年3月份春招成 ...

  5. 大疆FPGA/芯片开发工程师(A卷、B卷)笔试题详解

    大疆芯片开发岗A卷 文章目录 一.单选题 / 多选题 **说明:答案仅供参考,个别可能存在错误.** 一.单选题 / 多选题 1.(单选)关于流水线设计的理解,错误的是C   A.流水线可以提高系统并 ...

  6. 大疆FPGA/芯片开发工程师(B卷)笔试题(含详解)

    大疆芯片开发岗B卷 文章目录 一.单选题 二.多选题 三.填空题 四.问答题 **说明:答案仅供参考,个别可能存在错误.** 一.单选题 1.在UVM和SystemVerilog的基础知识中,描述错误 ...

  7. 大疆FPGA/芯片开发工程师(A卷)笔试题(含详解)

    大疆芯片开发岗A卷 文章目录 一.单选题 二.多选题 三.填空题 四.问答题 **说明:答案仅供参考,个别可能存在错误.** 一.单选题 1.下列关于多bit数据跨时钟域的处理思路,错误的有 A    ...

  8. 2018京东C++开发工程师实习面经

    本人大三软件工程专业,从上个月开始刷书准备面试,这是这么久以来第一次面试,有点小紧张小兴奋.昨天就从深圳过来广州,住在同学宿舍,昨晚探了路踩踩点.早上9点45分到广州希尔顿酒店,在4楼签到后等到10点 ...

  9. 京东软件开发工程师面试总结

    第一次工作面试,虽然成功了,但是有许多不足的地方,需要反思和改正. 因为时间与距离的原因,两次面试都是电话面试进行的,第一次面试一个面试官,面试时间将近20分钟,第二次面试,两个面试官先后问问题,整个 ...

最新文章

  1. 5G时代,微软又走对了一步棋!
  2. 运维企业专题(9)RHCS集群工具介绍
  3. 计算机网络(网络层,运输层和应用层的一些tips)
  4. java builder pattern_Java Builder Pattern建造者模式详解及实例
  5. 2011浙大878计算机专业基础综合大题答案解析
  6. 集成spring框架的web.xml
  7. 阿里开源 GNN 框架 Graph-Learn,实现了各类可复用模型和编程接口!
  8. 解决jquery组件样式冲突 jPicker实例
  9. 报错:[Microsoft][ODBC 驱动程序管理器] 无效的字符串或缓冲区长度
  10. 如何搭建监狱高清1080P OTT/IPTV电视系统
  11. SPSS教程-t检验怎么做?
  12. smartdns 部署最佳实践
  13. 计算机电源复位,关于Apple本本的电池复位(重置电源管理、电池重置)方法
  14. Piranha介绍:过期代码自动删除的开源工具
  15. 基于人脸识别的课堂考勤系统 tkinter+openpyxl+face_recognition
  16. JAVA版本号的问题 Java版本号与JDK版本
  17. Visual studio2022还原VC6环境设置
  18. 非阻塞IO处理上几个常见问题
  19. day5 安装Linux服务器面板管理工具
  20. 敬告青年---陈独秀

热门文章

  1. 离子感烟探测器的工作原理介绍
  2. 公众平台 java_java开发微信公众平台
  3. 根据epc和ra定位linux kernel panic或者应用程序的出错位置
  4. uniapp手机端图片缓存方案
  5. xampp mysql远程连接_XAMPP mysql远程连接
  6. 新唐单片机模拟IIC
  7. 珞珈-B生所学 跟学笔记 PPT(二)
  8. 牛客SQL实战—数据分析必备技能
  9. python绘制缓和曲线_在cad中画缓和曲线的绘制方法
  10. 计算机非全日制硕士 选校,报考攻略:2021年报考非全日制研究生该如何选择院校和专业?...