Effective objective-c-- 内存管理

Effective objective-c-- 内存管理

  • 前言
    • 理解引用计数
      • 引用计数工作原理
      • 属性存取方法中的内存管理
      • 自动释放池
      • 保留环
      • 要点
    • 以ARC简化引用计数
      • 使用ARC时必须遵循的方法和命名规则
      • 变量的内存管理语义
      • ARC如何清理实例变量
      • 覆写内存管理方法
      • 要点
    • 在dealloc方法中只释放引用并解除监听
      • 要点
    • 编写“异常安全代码“时留意内存管理问题
    • 以弱引用避免保留环
      • unsafe_unretained 和 weak
      • 要点
    • 以”自动释放池“释放内存峰值
      • 要点
      • 不要使用retainCount

前言

寒假比较忙没能能认真看,就拖到学校了来看了,进度落后很多了,只能尽量赶了;

理解引用计数

Objective-C 语言使用引用计数来管理内存,也就是说,每个对象都有个可以递增或递减的计数器。如果想使某个对象继续存活,那就递增其引用计数:用完了之后,就递减其计数。计数变为 0,就表示没人关注此对象了,于是,就可以把它销毁。

要注意开启ACR功能后,引用计数的方法无法使用 ;

引用计数工作原理

在引用计数架构下,对象有个计数器,用以表示当前有多少个事物想令此对象继续存活下去。这在 Objective-C 中叫做 “保留计数” (retain count),不过也可以叫 “引用计数”(reference count)。NSObject 协议声明了下面三个方法用于操作计数器,以递增或递减其值:

Retain 递增保留计数。
release 递减保留计数。
autorelease 待稍后清理 “自动释放池”(autorelease pool)时,再递减保留计数。

查看保留计数的方法叫做 retainCount,此方法不太有用

图演示了对象自创造出来之后历经一次 “保留” 及两次 “释放” 操作的过程。
 
在这里插入图片描述

使用引用计数的方法要关闭ACR,方法如下:在bulid settings->all->Combined->Apple Clang-language-oBjectiveC->Automatic Reference Counting设置为NO
在这里插入图片描述

看下面这段代码:

	        NSMutableArray* array = [[NSMutableArray alloc] init] ;
        NSNumber* number = [[NSNumber alloc] initWithInt:15] ;
//        [array addObject:number] ;
        [number release] ;
    NSLog(@"%@",number) ;
//        NSLog(@"%lu",(unsigned long)[number retainCount]) ;
//        NSLog(@"%@",[array objectAtIndex:0]) ;
        [array release] ;

上面这段代码我是想看看number在引用计数为0是调用该对象会不会崩溃,不过出乎意料的是是没有崩,这里的解释是:
在某些情况下,对已释放的对象进行访问可能不会立即导致崩溃。这是因为已释放的对象在内存中仍然存在一段时间,并且指针仍然指向该内存位置。这被称为“悬垂指针”(Dangling Pointer)。
当你尝试访问已释放的对象时,可能会发生以下情况之一:
你可能会幸运地访问到一个仍然有效的对象。在这种情况下,你可能不会立即遇到崩溃或错误。
你可能会访问到无效的对象或者已经被其他对象覆盖的内存。在这种情况下,你可能会遇到崩溃、内存访问错误或者其他不可预测的行为。

书上的例子:

 

```objectivec
NSMutableArray *array = [[NSMutableArray alloc] init];
    NSNumber *number = [[NSNumber alloc] initWithInt:2023];
    [array addObject:number];
    [number release];
    [array release];

创建数组之后,把number加入其中的时候,系统会为number retain一次,也就是number的引用计数为2,接下来不需要number对象的时候我们释放了它,在这个例子里能知道number的引用计数现在还为1

为了避免在不经意间使用了无效对象,一般relase之后都会清空指针,这样能保证不出现悬空指针

NSMutableArray *array = [[NSMutableArray alloc] init];
    NSNumber *number = [[NSNumber alloc] initWithInt:2023];
    [array addObject:number];
    [number release];
    [array release];
    number == nil;

属性存取方法中的内存管理

不光是数组,其他对象也可以保留别的对象,这一般通过访问 “属性”来实现,而访问属性时,会用到相关实例变量的获取方法及设置方法。若属性为 “strong 关系”(strong relationship),则设置的属性值会保留。比方说,有个名叫 foo 的属性由名为 _foo 的实例变量所实现,那么,该属性的设置方法会是这样:

在这里插入图片描述

此方法将保留新值并释放旧值,然后更新实例变量,令其指向新值。顺序很重要。假如还未保留新值就先把旧值释放了,而且两个值又指向同一个对象,那么,先执行的 release 操作就可能导致系统将此对象永久回收。而后续的 retain 操作则无法令这个已经彻底回收的对象复生,于是实例变量就成了悬挂指针了。(这里上面也提到了) ;

自动释放池

在 Objective-C 的引用计数架构中,自动释放池是一项重要特性。调用 release 会立刻递减对象的保留计数(而且还有可能令系统回收此对象),然而有时候可以不调用它,改为调用 autorelease,此方法会在稍后递减计数,通常是在下一次 “事件循环”(event loop)时递减,不过也可能执行得更早些。

在这里插入图片描述
对于上面这个方法,我们需要延迟str对象的回收释放,也就是说,我们要用automatic release ;

在这里插入图片描述

用 autorelease,它会在稍后释放对象,从而给调用者留下了足够长的时间,使其可以在需要时先保留返回值。换句话说,此方法可以保证对象在跨越 “方法调用边界”(method callboundary)后一定存活。实际上,释放操作会在清空最外层的自动释放池(参见第 34 条)时执行,除非你有自己的自动释放池,否则这个时机指的就是当前线程的下一次事件循环

autorelease 能延长对象生命周期,使其在跨越方法调用边界后依然可以存活一段时间。

保留环

使用引用计数机制时,经常要注意的一个问题就是 “保留环”(retain cycle),也就是呈环状相互引用的多个对象。这将导致内存泄漏,因为循环中的对象其保留计数不会降为 0。对于循环中的每个对象来说,至少还有另外一个对象引用着它。图里的每个对象都引用了另外两个对象之中的一个。在这个循环里,所有对象的保留计数都是 1。

在垃圾收集环境中,通常将这种情况认定为 “孤岛”(island of isolation)。此时,垃圾收集器会把三个对象全都回收走。而在 Objective-C 的引用计数架构中,则享受不到这一便利。通常采用 “弱引用”(weak reference,参见第 33 条)来解决此问题,或是从外界命令循环中的某个对象不再保留另外一个对象。这两种办法都能打破保留环,从而避免内存泄漏。

要点

  • 引用计数机制通过可以递增递减的计数器来管理内存。对象创建好之后,其保留计数至少为 1。若保留计数为正,则对象继续存活。当保留计数降为 0 时,对象就被销毁了。
  • 在对象生命期中,其余对象通过引用来保留或释放对象。保留于释放操作分别会递增及递减保留计数。

以ARC简化引用计数

在这里插入图片描述

此代码有内存泄漏问题,因为 if 语句块末尾并未释放 message 对象。由于在 if 语句之外无法引用 message,所以此对象所占的内存泄漏了(这里“泄漏”的意思是:没有正确释放已经不再使用的内存)。

  • 由于 ARC 会自动执行 retain、release 、autorelease 等操作,所以直接在 ARC 下调用这些内存管理方法是非法的。

ARC的优点除了方便外,还有:ARC 在调用这些方法时,并不通过普通的 Objective-C 消息派发机制,而是直接调用其底层 C 语言版本。这样做性能更好,因为保留及释放操作需要频繁执行,所以直接调用底层函数能节省很多 CPU 周期。

使用ARC时必须遵循的方法和命名规则

将内存管理语义在方法名中表示出来早已成为 Objective-C 的惯例,而 ARC 则将之确立为硬性规定。这些规则简单地体现在方法名上。若方法名以下列词语开头,则其返回的对象归调用者所有:

  • alloc
  • new
  • copy
  • mutableCopy

归调用者所有的意思是: 调用上述四种方法的那段代码要负责释放方法所返回的对象。也就是说,这些对象的保留计数是正值,而调用了这四种方法的那段代码要将其中一次保留操作抵消掉。

要注意:如果还有其他对象保留此对象,并对其调用了 autorelease,那么保留计数的值可能比 1 大,这也是 retainCount 方法不太有用的原因之一。

若方法名不以上述四个词语开头,则表示其所返回的对象并不归调用者所有。 在这种情况下,返回的对象会自动释放

维系这些规则所需的全部内存管理事宜均由 ARC 自动处理

变量的内存管理语义

ARC 也会处理局部变量与实例变量的内存管理。
默认情况下,每个变量都是指向对象的强引用。

对于以下的代码:
在这里插入图片描述
在非ARC下执行的setter方法的实现是这样的:
在这里插入图片描述

但这个方法很明显是不安全的,如果只有当前对象还在引用这个值,那么设置方法中的释放操作会使该值的保留计数降为0,从而导致系统将其回收。接下来再执行保留操作,就会令应用程序崩溃。

ARC 会用一种安全的方式来设置:先保留新值,再释放旧值,最后设置实例变量。

在应用程序中,可用下列修饰符来改变局部变量与实例变量的语义:

__strong: 默认语义,保留此值。
__unsafe_unretained: 不保留此值,这么做可能不安全,因为等到再次使用变量时,其对象可能已经回收了。
__weak: 不保留此值,但是变量可以安全使用,因为如果系统把这个对象回收了,那么变量也会自动清空。
__autoreleasing: 把对象 “按引用传递” (pass by reference)给方法时,使用这个特殊的修饰符。此值在方法返回时自动释放。

  • 我们经常会给局部变量加上修饰符,用以打破由“块”(block),所引入的“保留环”(retain cycle)。块会自动保留其所捕获的全部对象,而如果这其中有某个对象又保留了块本身,那么就可能导致 “保留环”。可以用 __weak 局部变量来打破这种 “保留环”:

ARC如何清理实例变量

要管理其内存,ARC 就必须在 “回收分配给对象的内存”(deallocate)
当手动管理引用计数时,你可能会像下面这样自己来编写 dealloc 方法:
在这里插入图片描述

如果有非 Objective-C 的对象,不需要像原来那样调用超类的 dealloc 方法。
ARC 环境下,dealloc 方法可以像这样写:
在这里插入图片描述

因为 ARC 会自动生成回收对象时所执行的代码,所以通常无须再编写 dealloc 方法。这能减少项目源代码的大小,而且可以省去其中一些样板代码(boilerplate code)。

覆写内存管理方法

不使用ARC时,可以覆写内存管理方法。比方说,在实现单例类的时候,因为单例不可释放,所以我们经常覆写release方法,将其替换为“空操作”

要点

  • 有 ARC 之后,程序员就无须担心内存管理问题了。使用 ARC 来编程,可省去类中的许多 “样板代码”。
  • ARC 管理对象生命期的办法基本上就是:在合适的地方插入 “保留” 及 “释放”操作。
  • 在 ARC 环境下,变量的内存管理语义可以通过修饰符指明,而原来需要手工执行 “保留” 及 “释放”操作。
  • 由方法所返回的对象,其内存管理语义总是通过方法名来体现。ARC 将此确定为开发者必须遵守的规则。
  • ARC 只负责管理 Objective-C 对象的内存。尤其要注意: CoreFoundation 对象不归 ARC
    管理,开发者必须适时调用 CFRetain/CFRelease。

在dealloc方法中只释放引用并解除监听

对象在经历其生命期后,最终会为系统所回收,这时就要执行 dealloc 方法了。在每个对象的生命期内,此方法仅执行一次,也就是当保留计数降为 0 的时候。
实际上,程序库会以开发者察觉不到的方式操作对象,从而使回收对象的真正时机和预期的不同。你决不应该自己调用 dealloc 方法,运行期系统会在适当的时候调用它。

那么,应该在 dealloc 方法中做什么呢?

主要就是释放对象所拥有的引用,也就是把所有 Objective-C 对象都释放掉,对象所拥有的其他非 Objective-C 对象也要释放。比如 CoreFoundation 对象就必须手工释放,因为它们是由纯C 的API 所生成的。
所以可以是:
在这里插入图片描述

最好还要加上[super dealloc] ;

编写 dealloc 方法时还需要注意,不要在里面随便调用其他方法。

  • 如果在这里所调用的方法又要异步执行某些任务,或是又要继续调用它们自己的某些方法,那么等到那些任务执行完毕时,系统已经把当前这个待回收的对象彻底摧毁了。这会导致很多问题,且经常使应用程序崩溃,因为那些任务执行完毕后,要回调此对象,告诉该任务已完成,而此时如果对象已摧毁,那么回调操作就回出错。
  • 在 dealloc 里也不要调用属性的存取方法,因为有人可能会覆写这些方法,并与其中做一些无法在回收阶段安全执行的操作。

要点

  • 在 dealloc 方法里,应该做的事情就是释放指向其他对象的引用,并取消原来订阅的“键值观测”(KVO)或
    NSNOtificationCenter 等通知,不要做其他事情。
  • 如果对象持有文件描述符等系统资源,那么应该专门编写一个方法来释放此种资源。这样的类要和其使用者约定: 用完资源后必须调用 close
    方法。
  • 执行异步任务的方法不应该在 dealloc 里调用; 只能在正常状态下执行的那些方法也不应在 dealloc
    里调用,因为此时对象已处于正在回收的状态了。

编写“异常安全代码“时留意内存管理问题

纯 C 中没有异常,而 C++ 与 Objective-C 都支持异常。在当前的运行期系统中,C++ 与 Objective-C 的异常相互兼容,也就是说,从其中一门语言里抛出的异常能用另外一门语言所编写的 “异常处理程序”(exception handler)来捕获。

比如使用 Objective-C++ 来编码时,或是编码中用到了第三方程序库而此程序库所抛出的异常又不受你控制时,就需要捕获及处理异常了。

C++ 的析构函数(destructor)由 Objective-C 的异常处理例程(exception-handle routine)来运行。这对于 C++ 对象很重要,由于抛出异常会缩短其生命周期,所以发生异常时必须析构,不然就会泄漏,

手动管理的方式如下:
在这里插入图片描述

但上面的方法中,如果dosomethingThatMayThrow方法判断抛出异常,会直接进入catch块,所以没能release导致内存泄漏,解决方法时在设一个@finalllay块,将release操作放到其中。

以弱引用避免保留环

首先我们要了解什么是保留环:
对象图里经常会出现一种情况,就是几个对象都以某种方式互相引用,从而形成“环”(cycle)。由于 Objective-C 内存管理模型使用引用计数架构,所以这种情况通常会泄漏内存,因为最后没有别的东西会引用环中的对象。

下面给一个书上的例子;
在这里插入图片描述
两个类之间的引用关系如图:
在这里插入图片描述
上面就是一个简单的保留环,即使外界不在引用这两个对象,这两个对象依赖于彼此的引用关系,其引用计数不会降到0,即他们不会被系统自动回收,造成内存泄漏 ;
下面用图表示一个更复杂的保留环,
在这里插入图片描述
如果只剩一个引用还指向保留环中的实例,而现在又把这个引用移除,那么整个保留环就泄漏了。也就是说,没办法再访问其中的对象了。图中所示的保留环更复杂一些,其中有四个对象,只有 ObjectB 还为外界所引用,把仅有的这个引用移除之后,四者所占内存就泄漏了。
避免保留环的最佳方式就是弱引用。这种引用经常用来表示 “非拥有关系”(nonowning relationship)。将属性声明为 unsafe_unretained
可以把上面的代码修改成下面这样:
在这里插入图片描述
修改之后,EOCClassB 实例就不再通过 other 属性来拥有 EOCClassA 实例了。属性特质 (attribute) 中的 unsafe_unretained 一词表明,属性值可能不安全,而且不归此实例所拥有。如果系统已经把属性所指的那个对象回收了,那么在其上调用方法可能会使应用程序崩溃。由于本对象并不保留属性对象,因此其有可能为系统所回收。

unsafe_unretained 和 weak

weak与 unsafe_unretained 的作用完全相同。然而,只要系统把属性回收,属性值就会自动设为 nil。
使用 weak 而非 unsafe_unretained 引用可以令代码更安全。应用程序也许会显示出错误的数据,但不会直接崩溃。这么做显然比令终端用户直接看到程序退出要好。

要点

  • 将某些引用设为 weak,可避免出现 “保留环”。
  • weak 引用可以自动清空,也可以不自动清空。自动清空(autonilling)是随着 ARC
    而引入的新特性,由运行期系统来实现。在具备自动清空功能的弱引用上,可以随意读取其数据,因为这种引用不会指向已经回收过的对象。

以”自动释放池“释放内存峰值

创建自动释放池所用语法如下:
在这里插入图片描述
一般情况下无须担心自动释放池的创建问题。
通常只有一个地方需要创建自动释放池,那就是在 main 函数里,我们是自动释放池来包裹应用程序的主入口点 (main application entry point)。
在这里插入图片描述
自动释放池于左花括号处创建,并于对应的右花括号处自动清空。位于自动释放池范围内的对象,将在此范围末尾处收到 release 消息。自动释放池可以嵌套。系统在自动释放对象时,会把它放到最内层的池里。
在这里插入图片描述
将自动释放池嵌套用的好处是,可以借此控制应用程序的内存峰值,使其不致过高。

在这里插入图片描述
上面这段代码的for循环中会产生许多多余的变量占用内存,由于无法通过指针来直接调用release来释放内存,所以这里最好设置自动释放池来控制内存

自动释放池机制就像 “栈”(stack)一样。系统创建好自动释放池之后,就将其推入栈中,而清空自动释放池,则相当于将其从栈中弹出。在对象上执行自动释放操作,就等于将其放入栈顶的那个池里。

是否应该用池来优化效率,完全取决于具体的应用程序。首先得监控内存用量,判断其中有没有需要解决的问题,如果没完成这一步,那就别急着优化。尽管自动释放池块的开销不太大,但毕竟还是有的,所以尽量不要建立额外的自动释放池。

要点

  • 自动释放池排布在栈中,对象收到 autorelease 消息后,系统将其放入最顶端的池里。
  • 合理运用自动释放池,可降低应用程序的内存峰值。
  • @autoreleasepool 这种新式写法能创建出更为轻便的自动释放池。

不要使用retainCount

如果在 ARC 中调用,编译器就会报错,这和在 ARC 中调用 retain、release、autorelease 方法时的情况一样。虽然此方法已经正式废弃了,但还是经常有人误解它,其实这个方法根本就不应该调用。若在不启用 ARC 的环境下编程(说真的,还是在 ARC 下编程比较好),那么仍可调用此方法,而编译器不会报错。
此方法之所以无用,其首要原因在于:它返回的保留计数只是某个给定时间点上的值。该方法并未考虑到系统会稍后把自动释放池清空,因而不会将后续的释放操作从返回值里减去,这样的话,此值就未必能真实反映实际的保留计数了。
那么,只为了调试而使用 retainCount 方法行不行呢?即便只为调试,此方法也不是很有用。由于对象可能处在自动释放池中,所以其保留计数未必如想象般精确。而且其他程序库也可能自行保留或释放对象,这都会扰乱保留计数的具体取值。看了具体的计数值之后,你可能还误以为是自己的代码修改了它,殊不知其实是由深埋在另外一个程序库中的某段代码所改的。

  • 对象的保留计数看似有用,实则不然,因为任何给定时间点上的“绝对保留计数”(absolute retain
    count)都无法反映对象生命期的全貌。
  • 引入 ARC 之后,retainCount 方法就正式废止了,在 ARC 下调用该方法会导致编译器报错。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据分享】2000~2022年中国区域MOD16A2GF V061 潜在蒸散发PET数据

各位同学们好,今天和大伙儿分享的是2000~2022年中国区域MOD16A2GF V061 潜在蒸散发PET数据。如果大家有下载处理数据等方面的问题,您可以私信或者评论。 Running, S., Mu, Q., Zhao, M., Moreno, A. (2021). MODIS/Terra Net Evapotranspiration Gap-Fil…

[JavaWeb玩耍日记]HTML+CSS+JS快速使用

目录 一.标签 二.指定css 三.css选择器 四.超链接 五.视频与排版 六.布局测试 七.布局居中 八.表格 九.表单 十.表单项 十一.JS引入与输出 十二.JS变量,循环,函数 十三.Array与字符串方法 十四.自定义对象与JSON 十五.BOM对象 十六.获取…

模型部署 - onnx 的导出和分析 -(1) - PyTorch 导出 ONNX - 学习记录

onnx 的导出和分析 一、PyTorch 导出 ONNX 的方法1.1、一个简单的例子 -- 将线性模型转成 onnx1.2、导出多个输出头的模型1.3、导出含有动态维度的模型 二、pytorch 导出 onnx 不成功的时候如何解决2.1、修改 opset 的版本2.2、替换 pytorch 中的算子组合2.3、在 pytorch 登记&…

deep learning with pytorch(一)

1.create a basic nerual network model with pytorch 数据集 Iris UCI Machine Learning Repository fully connected 目标:创建从输入层的代码开始,向前移动到隐藏层,最后到输出层 # %% import torch import torch.nn as nn import torch.nn.funct…

Angular基础---HelloWorld---Day1

文章目录 1. 创建Angular 项目2.对Angular架构的最基本了解3.创建并引用新的组件(component)4.对Angular架构新的认识(多组件)5.组件中业务逻辑文件的编辑(ts文件)6.标签中属性的绑定(1) ID的绑定(2) class…

AI大模型与小模型之间的“脱胎”与“反哺”(第二篇)

此图片来源于网络 21. **跨模态学习(Cross-Modal Learning)**: 如果各个行业AI小模型涉及多种数据类型或模态,可以通过跨模态学习技术让大模型理解并整合这些不同模态之间的关联,从而提升对多行业复杂问题的理解和解…

【Redis 主从复制】

文章目录 1 :peach:环境配置:peach:1.1 :apple:三种配置方式:apple:1.2 :apple:验证:apple:1.3 :apple:断开复制和切主:apple:1.4 :apple:安全性:apple:1.5 :apple:只读:apple:1.6 :apple:传输延迟:apple: 2 :peach:拓扑结构:peach:2.1 :apple:⼀主⼀从结构:apple:2.2 :apple:⼀…

【FPGA/IC】CRC电路的Verilog实现

前言 在通信过程中由于存在各种各样的干扰因素,可能会导致发送的信息与接收的信息不一致,比如发送数据为 1010_1010,传输过程中由于某些干扰,导致接收方接收的数据却成了0110_1010。为了保证数据传输的正确性,工程师们…

30天JS挑战(第十五天)------本地存储菜谱

第十五天挑战(本地存储菜谱) 地址:https://javascript30.com/ 所有内容均上传至gitee,答案不唯一,仅代表本人思路 中文详解:https://github.com/soyaine/JavaScript30 该详解是Soyaine及其团队整理编撰的,是对源代…

【数据结构】B树

1 B树介绍 B树(英语:B-tree),是一种在计算机科学自平衡的树,能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除的动作,都在对数时间内完成。B树,概括来说是一个一般化的…

CAS外部云迁移vmware虚拟机兼容性问题处理

CAS外部云迁移vmware虚拟机兼容性问题处理 1、迁移过程中报错实图 2、问题原因 打开虚拟机存储的位置,发现文件夹下存在ctk.vmdk的文件 3、在vmware右键虚拟机编辑设置 注:虚拟机需要先关机 点击虚拟机选项——高级——编辑设置 将ctk.ENABLED改为…

第五套CCF信息学奥赛c++练习题 CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(选择题)

第五套中小学信息学奥赛CSP-J考前冲刺题 1、不同类型的存储器组成了多层次结构的存储器体系,按存取速度从快到慢排列的是 A、快存/辅存/主存 B、外存/主存/辅存 C、快存/主存/辅存 D、主存/辅存/外存 答案:C 考点分析:主要考查计算机相关知识&…

在ubuntu上安装hadoop完分布式

准备工作 Xshell安装包 Xftp7安装包 虚拟机安装包 Ubuntu镜像源文件 Hadoop包 Java包 一、安装虚拟机 创建ubuntu系统 完成之后会弹出一个新的窗口 跑完之后会重启一下 按住首先用ctrlaltf3进入命令界面,输入root,密码登录管理员账号 按Esc 然后输入 …

蓝牙BLE 5.0、5.1、5.2和5.3区别

随着科技的不断发展,蓝牙技术也在不断进步,其中蓝牙BLE(Bluetooth Low Energy)是目前应用广泛的一种蓝牙技术,而BLE 5.0、5.1、5.2和5.3则是其不断升级的版本。本文将对这四个版本的区别进行详细的比较。 一、BLE 5.0…

为啥要用C艹不用C?

在很多时候,有人会有这样的疑问 ——为什么要用C?C相对于C优势是什么? 最近两年一直在做Linux应用,能明显的感受到C带来到帮助以及快感 之前,我在文章里面提到环形队列 C语言,环形队列 环形队列到底是怎么回…

FPGA高端项目:FPGA基于GS2971的SDI视频接收+纯verilog图像缩放+多路视频拼接,提供8套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收转HDMI输出应用本方案的SDI接收图像缩放应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收HLS动态字符叠加输出应用本方案的SDI接收HLS多路视频融合叠加应用本方案的SDI接收GTX…

【代码】Android|获取压力传感器、屏幕压感数据(大气压、原生和Processing)

首先需要分清自己需要的是大气压还是触摸压力,如果是大气压那么就是TYPE_PRESSURE,可以参考https://source.android.google.cn/docs/core/interaction/sensors/sensor-types?hlzh-cn。如果是触摸压力就是另一回事,我需要的是触摸压力。 不过…

【算法沉淀】刷题笔记:并查集 带权并查集+实战讲解

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘&am…

Windows Server 各版本搭建文件服务器实现共享文件(03~19)

一、Windows Server 2003 打开服务器,点击左下角开始➡管理工具➡管理您的服务器➡添加或删除角色 点击下一步等待测试 勾选自定义配置,点击下一步 选择文件服务器,点击下一步 勾选设置默认磁盘空间,数据自己更改,最…

Onenote软件新建笔记本时报错:无法在以下位置新建笔记本

报错现象: 当在OneNote软件上,新建笔记本时: 然后,尝试重新登录微软账户,也不行,提示报错: 解决办法: 打开一个新的记事本,复制粘贴以下内容: C:\Users\Adm…