ASAN

文章目录

    • ASAN 简介
    • 实例一,检测内存泄漏
    • 实例二,检测悬空指针访问
    • 实例三,检测堆溢出
    • 实例四,检测栈溢出
    • ASAN 原理
    • 使用技巧
    • KASAN

ASAN 简介

ASAN 是 Address Sanitizer 的简称,是 GCC 自带的内存问题检查工具,比较轻量级,非常适合单元测试时检查内存问题。
使用也比较简单,只需要在编译时加上 -fsanitize=address 选项即可。若想更精确查看到源码位置,可以加上 -g 选项。

实例一,检测内存泄漏

leak.c

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
	char *s;

	s = (char *)malloc(100);
	strcpy(s, "hello world");
	printf("string is: %s\n", s);

	return 0;
}

编译

$ gcc leak.c -o leak.out -g -fsanitize=address

运行

$ ./leak.out 
string is: hello world

=================================================================
==5655==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 100 byte(s) in 1 object(s) allocated from:
    #0 0x7f34793ce808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x55fbf399c225 in main /home/liyongjun/project/c/C_study/memory/asan/leak.c:10
    #2 0x7f34790f3082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: 100 byte(s) leaked in 1 allocation(s).

上述代码中,分配了 100 字节堆内存,但在 main 函数返回前始终没有释放。
ASAN 提供的报告说明了错误原因是 detected memory leaks(检测到内存泄漏), 同时指出,泄漏的内存是在 leak.c 的第 10 行分配的。
有了这么准确且易用的工具,内存泄漏问题是不是没那么头疼了。

实例二,检测悬空指针访问

huaf.c

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
	char *s;

	s = (char *)malloc(100);

	free(s);

	strcpy(s, "hello world");
	printf("string is: %s\n", s);

	return 0;
}

编译

$ gcc huaf.c -o huaf.out -g -fsanitize=address

运行

$ ./huaf.out 
=================================================================
==5939==ERROR: AddressSanitizer: heap-use-after-free on address 0x60b0000000f0 at pc 0x7f674231b58d bp 0x7ffeb4a7bc30 sp 0x7ffeb4a7b3d8
WRITE of size 12 at 0x60b0000000f0 thread T0
    #0 0x7f674231b58c in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x556af56bc26d in main /home/liyongjun/project/c/C_study/memory/asan/huaf.c:14
    #2 0x7f67420b2082 in __libc_start_main ../csu/libc-start.c:308
    #3 0x556af56bc16d in _start (/home/liyongjun/project/c/C_study/memory/asan/huaf.out+0x116d)

0x60b0000000f0 is located 0 bytes inside of 100-byte region [0x60b0000000f0,0x60b000000154)
freed by thread T0 here:
    #0 0x7f674238d40f in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:122
    #1 0x556af56bc255 in main /home/liyongjun/project/c/C_study/memory/asan/huaf.c:12
    #2 0x7f67420b2082 in __libc_start_main ../csu/libc-start.c:308

previously allocated by thread T0 here:
    #0 0x7f674238d808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x556af56bc245 in main /home/liyongjun/project/c/C_study/memory/asan/huaf.c:10
    #2 0x7f67420b2082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: heap-use-after-free ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c167fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c167fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c167fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c167fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c167fff8000: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
=>0x0c167fff8010: fd fd fd fd fd fa fa fa fa fa fa fa fa fa[fd]fd
  0x0c167fff8020: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c167fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c167fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==5939==ABORTING

上述代码中我们分配了100个字节的内存空间,紧接着将其释放,但接下来我们对之前分配的内存地址执行写入操作,这是典型的悬空指针非法访问。
ASAN 指出错误原因是 heap-use-after-free(访问悬空指针),该内存地址是:0x60b0000000f0,同时还给出了发生错误时 PC、BP、SP 寄存器的值。
指出错误发生在 huaf.c 的第 14 行。
并且还指出这段内存何时被申请,何时已被释放。

实例三,检测堆溢出

overflow.c

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
	char *s;

	s = (char *)malloc(10);
	strcpy(s, "hello world");
	printf("string is: %s\n", s);

	return 0;
}

编译

$ gcc overflow.c -o overflow.out -g -fsanitize=address

运行

$ ./overflow.out 
=================================================================
==6026==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000001a at pc 0x7f8b7f21a58d bp 0x7ffe19791730 sp 0x7ffe19790ed8
WRITE of size 12 at 0x60200000001a thread T0
    #0 0x7f8b7f21a58c in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790
    #1 0x56188b58b241 in main /home/liyongjun/project/c/C_study/memory/asan/overflow.c:11
    #2 0x7f8b7efb1082 in __libc_start_main ../csu/libc-start.c:308
    #3 0x56188b58b14d in _start (/home/liyongjun/project/c/C_study/memory/asan/overflow.out+0x114d)

0x60200000001a is located 0 bytes to the right of 10-byte region [0x602000000010,0x60200000001a)
allocated by thread T0 here:
    #0 0x7f8b7f28c808 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cc:144
    #1 0x56188b58b225 in main /home/liyongjun/project/c/C_study/memory/asan/overflow.c:10
    #2 0x7f8b7efb1082 in __libc_start_main ../csu/libc-start.c:308

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:790 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa 00[02]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==6026==ABORTING

上面这段代码我们只分配了 10 个字节,但在随后操作中写入了 12 字节的数据,此时,数据的写入显然是溢出分配的内存块了。
ASAN 告诉我们错误的原因是:heap-buffer-overflow,堆区内存溢出了,问题代码为 overflow.c 的第 11 行。

实例四,检测栈溢出

sbo.c

#include <stdio.h>

int main(int argc, char *argv[])
{
	int array[100];

	array[100] = 1;

	return 0;
}

编译

$ gcc sbo.c -o sbo.out -g -fsanitize=address

运行

$ ./sbo.out 
=================================================================
==6154==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffef64bd350 at pc 0x560368c3c2ae bp 0x7ffef64bd170 sp 0x7ffef64bd160
WRITE of size 4 at 0x7ffef64bd350 thread T0
    #0 0x560368c3c2ad in main /home/liyongjun/project/c/C_study/memory/asan/sbo.c:7
    #1 0x7f10ec5fc082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x560368c3c10d in _start (/home/liyongjun/project/c/C_study/memory/asan/sbo.out+0x110d)

Address 0x7ffef64bd350 is located in stack of thread T0 at offset 448 in frame
    #0 0x560368c3c1d8 in main /home/liyongjun/project/c/C_study/memory/asan/sbo.c:4

  This frame has 1 object(s):
    [48, 448) 'array' (line 5) <== Memory access at offset 448 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/liyongjun/project/c/C_study/memory/asan/sbo.c:7 in main
Shadow bytes around the buggy address:
  0x10005ec8fa10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fa20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fa30: 00 00 f1 f1 f1 f1 f1 f1 00 00 00 00 00 00 00 00
  0x10005ec8fa40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fa50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10005ec8fa60: 00 00 00 00 00 00 00 00 00 00[f3]f3 f3 f3 f3 f3
  0x10005ec8fa70: f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fa80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fa90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8faa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10005ec8fab0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==6154==ABORTING

上面的代码,我们在栈上创建了一个容量为100的数组,但在随后的写入操作中在超过数据容量的地址上写入数据,导致了栈溢出。
ASAN 指出错误原因是 stack-buffer-overflow(栈溢出),出错代码位置是 sbo.c 第 7 行。

ASAN 原理

在编译时,ASAN 通过 libasan.so 替换 malloc 和 free 接口。ASAN 会接管内存申请接口,即用户的内存全都由 ASAN 来管理。
在程序申请内存时,ASAN 会额外分配一部分内存来标识该内存的状态。
在程序使用内存时,ASAN 会额外进行判断,确认该内存是否可以被访问,并在访问异常时输出错误信息。

编译前:

*address = ...;  // or: ... = *address;

编译后:

if (IsPoisoned(address)) {
	ReportError(address, kAccessSize, kIsWrite);
}
*address = ...;  // or: ... = *address;

该方式的关键点就在于读写内存前会判断地址是否处于“中毒”状态。

使用技巧

如果你觉得 ASAN 插桩代码和检测的对你某些的代码来说太慢了,那么可以使用编译器标志来禁用特定函数的,使 ASAN 跳过对代码中某个函数的插桩和检测, 跳过分析函数的编译器指令是:

__attribute__((no_sanitize_address))

KASAN

KASAN 是 Kernel Address Sanitizer 的缩写,ASAN 用于用户空间,KASAN 则用于内核空间。
KASAN 集成在 Linux 内核中,随 Linux 内核代码一起发布。

要启用 KASAN,请使用以下命令配置内核:

CONFIG_KASAN = y

典型的越界访问报告如下所示:

==================================================================
BUG: AddressSanitizer: out of bounds access in kmalloc_oob_right+0x65/0x75 [test_kasan] at addr ffff8800693bc5d3
Write of size 1 by task modprobe/1689
=============================================================================
BUG kmalloc-128 (Not tainted): kasan error
-----------------------------------------------------------------------------

Disabling lock debugging due to kernel taint
INFO: Allocated in kmalloc_oob_right+0x3d/0x75 [test_kasan] age=0 cpu=0 pid=1689
 __slab_alloc+0x4b4/0x4f0
 kmem_cache_alloc_trace+0x10b/0x190
 kmalloc_oob_right+0x3d/0x75 [test_kasan]
 init_module+0x9/0x47 [test_kasan]
 do_one_initcall+0x99/0x200
 load_module+0x2cb3/0x3b20
 SyS_finit_module+0x76/0x80
 system_call_fastpath+0x12/0x17
INFO: Slab 0xffffea0001a4ef00 objects=17 used=7 fp=0xffff8800693bd728 flags=0x100000000004080
INFO: Object 0xffff8800693bc558 @offset=1368 fp=0xffff8800693bc720

Bytes b4 ffff8800693bc548: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a  ........ZZZZZZZZ
Object ffff8800693bc558: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc568: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc578: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc588: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc598: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc5a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc5b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
Object ffff8800693bc5c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5  kkkkkkkkkkkkkkk.
Redzone ffff8800693bc5d8: cc cc cc cc cc cc cc cc                          ........
Padding ffff8800693bc718: 5a 5a 5a 5a 5a 5a 5a 5a                          ZZZZZZZZ
CPU: 0 PID: 1689 Comm: modprobe Tainted: G    B          3.18.0-rc1-mm1+ #98
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
 ffff8800693bc000 0000000000000000 ffff8800693bc558 ffff88006923bb78
 ffffffff81cc68ae 00000000000000f3 ffff88006d407600 ffff88006923bba8
 ffffffff811fd848 ffff88006d407600 ffffea0001a4ef00 ffff8800693bc558
Call Trace:
 [<ffffffff81cc68ae>] dump_stack+0x46/0x58
 [<ffffffff811fd848>] print_trailer+0xf8/0x160
 [<ffffffffa00026a7>] ? kmem_cache_oob+0xc3/0xc3 [test_kasan]
 [<ffffffff811ff0f5>] object_err+0x35/0x40
 [<ffffffffa0002065>] ? kmalloc_oob_right+0x65/0x75 [test_kasan]
 [<ffffffff8120b9fa>] kasan_report_error+0x38a/0x3f0
 [<ffffffff8120a79f>] ? kasan_poison_shadow+0x2f/0x40
 [<ffffffff8120b344>] ? kasan_unpoison_shadow+0x14/0x40
 [<ffffffff8120a79f>] ? kasan_poison_shadow+0x2f/0x40
 [<ffffffffa00026a7>] ? kmem_cache_oob+0xc3/0xc3 [test_kasan]
 [<ffffffff8120a995>] __asan_store1+0x75/0xb0
 [<ffffffffa0002601>] ? kmem_cache_oob+0x1d/0xc3 [test_kasan]
 [<ffffffffa0002065>] ? kmalloc_oob_right+0x65/0x75 [test_kasan]
 [<ffffffffa0002065>] kmalloc_oob_right+0x65/0x75 [test_kasan]
 [<ffffffffa00026b0>] init_module+0x9/0x47 [test_kasan]
 [<ffffffff810002d9>] do_one_initcall+0x99/0x200
 [<ffffffff811e4e5c>] ? __vunmap+0xec/0x160
 [<ffffffff81114f63>] load_module+0x2cb3/0x3b20
 [<ffffffff8110fd70>] ? m_show+0x240/0x240
 [<ffffffff81115f06>] SyS_finit_module+0x76/0x80
 [<ffffffff81cd3129>] system_call_fastpath+0x12/0x17
Memory state around the buggy address:
 ffff8800693bc300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8800693bc380: fc fc 00 00 00 00 00 00 00 00 00 00 00 00 00 fc
 ffff8800693bc400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8800693bc480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8800693bc500: fc fc fc fc fc fc fc fc fc fc fc 00 00 00 00 00
>ffff8800693bc580: 00 00 00 00 00 00 00 00 00 00 03 fc fc fc fc fc
                                             ^
 ffff8800693bc600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8800693bc680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff8800693bc700: fc fc fc fc fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8800693bc780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff8800693bc800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

报告的标题描述了发生了什么类型的错误以及导致它的访问类型。

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

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

相关文章

【SpringBoot】00 Maven配置及创建项目

一、Maven配置 1、下载Maven 进入官网下载&#xff1a;Maven – Welcome to Apache MavenMaven – Download Apache Maven 本文以最新版为例&#xff0c;可按需选择版本 Maven – Welcome to Apache Maven 2、解压下载好的安装包 将安装包解压到自己设置的空文件夹中 3、…

抽象的代理模式1.0版本

前言&#xff1a; 在阅读Spring Security官方文档时&#xff0c;里面设计到了一种设计模式——代理模式Proxy 众里寻她千百度&#xff0c;蓦然回首&#xff0c;那人却在灯火阑珊处 开始 在之前的文章里陈述了一个观点——编程语言和语言没有区别 现看看我们日常生活中的代理…

利用 easycode 自动生成 数据库表 对应 类文件

1、安装easycode 打开settings&#xff0c;在plugins中搜索easycode进行安装&#xff0c;安装完成后重启idea。 2、连接数据库 连接数据库&#xff0c;填写数据库配置信息 点解Test connetction测试连接&#xff0c; 3、生成文件 右键数据库表格&#xff0c;生成对应文件 4…

说方法不如传授经验向媒体投稿你可以这样

在信息爆炸的时代,作为单位的信息宣传员,肩负着将本单位的重要资讯、活动成果、政策解读等内容有效传播至公众视野的重任。其中,向各类媒体投稿无疑是实现这一目标的重要途径。然而,传统的邮件投稿方式常常让我深感力不从心,费时费力不说,成功率低、出稿慢等问题更是让我和领导…

商标申请注册交费就一定会下注册证?

近日遇到一个网友说普推知产老杨说&#xff0c;他以为商标交钱就一定会下商标注册证&#xff0c;这个不管找哪家也做不到的。商标申请注册时要给商标局交费用&#xff0c;交完费用商标才有商标的形式审查&#xff0c;通过后下受理书&#xff0c;才有后面商标实质审查&#xff0…

[柏鹭杯 2021]试试大数据分解?

题目&#xff1a;&#xff08;NSSCTF | 在线CTF平台&#xff09; 题目就是如此&#xff0c;我没看到有5个不同的文本&#xff0c;其中最后一个文本以pem后缀&#xff0c;所以我们先来了解一下什么是pem格式。 PEM 格式 PEM格式通常用于数字证书认证机构&#xff08;Certifica…

UI自动化测试框架:PO 模式+数据驱动(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、PO 设计模式简介 什么是 PO 模式&#xff1f; PO&#xff…

雅特力AT32F435学习——2.ADC实验

ADC实验 ADC是什么、重要性就不再这里多说&#xff0c;ADC这个外设以及关于ADC的应用程序用途非常之广泛很值得深挖&#xff0c;接下来就让我们学一下雅特力AT32F435单片机的ADC吧。 基础知识 不同厂商的单片机的ADC外设都是有区别的&#xff0c;比如ADC转换位数、采样频率等…

【SpringCloud】OpenFeign高级特性

【SpringCloud】OpenFeign高级特性 文章目录 【SpringCloud】OpenFeign高级特性1. 超时控制1.1 全局配置1.2 指定配置 2. 重试机制3. 替换Http客户端3.1 引入依赖3.2 配置 4. 请求/响应压缩5. 日志打印6. 综合配置 1. 超时控制 默认OpenFeign客户端等待60秒钟&#xff0c;但是服…

传承汉字,发扬光大!让《米小圈动画汉字》也出一份力吧!

目前社会上出现的诸如“计算机是汉字的掘慕人”、“汉字是行将就木的老人”“必须废除汉字,汉字要走拼音化迷路”等观点,值得重视。专家们说,20年前如提汉字要走拼音化道路,主要是缘于汉字难以输入电脑,而时至今日,汉字在电脑上早已畅通无阻,如果仍坚持“汉字拙劣,必得用拼音文…

SAP 如何控制生产订单发料后不能删除组件

SAP默认的情况下,即使工单中的组件已发料了,但仍可以进行删除的标志。这种情况是不太符合逻辑的,如果真要删除,应该先退料,然后再上删除标志。并不能再物料还是已领料的状态下 就对物料做删除的操作。 如下图 生产订单在已经领料的情况下,仍然的被打上了删除标识。 我们…

【产品经理修炼之道】- 从需求到功能的转化过程

产品经理的最大作用是将需求转化为产品或者功能&#xff0c;从需求到功能&#xff0c;会经历哪些过程&#xff1f;本文总结了从需求到功能的转化过程&#xff0c;希望对你进一步了解有所帮助。 “大部分的产品经理特别是数字化产品经理其核心价值就是如何去解决如何把需求转化为…

MySQL主键:自增id、UUID、雪花算法

视频可看&#xff1a; 动画讲解&#xff1a;为什么不能使用自增ID或者UUID做MySQL的主键&#xff0c;雪花算法生成的主键存在哪些问题_哔哩哔哩_bilibili 一、MySQL分布式架构中&#xff0c;为什么不能使用自增id作为主键 自增主键的好处&#xff1a;写入效率高 弊端&#x…

你只可以转让未使用“通过 Apple 登录”功能的 App。

你只可以转让未使用“通过 Apple 登录”功能的 App。 因为这个问题遇到的比较少&#xff0c;同时也比较难以解决&#xff0c;所以这个问题的答案&#xff0c;必须要开会员我才让你们看。 华丽的开会员分割线 当前问题的主要原因是被接入的账号有30天的封号提示了&#xff0c;…

12(第十一章,数据仓库和商务智能)

目录 概述 目标和原则 基本概念 商务智能 数据仓库 数据仓库建设方法 数据仓库架构组件 加载处理方式 1、历史数据 2、批量变更数据捕获&#xff08;CDC&#xff09; 3、准实时和实时数据加载 活动 运营分析应用 方法 数据仓库构建 架构演进 数据处理过程 数…

Python+Selenium基于PO模式的Web自动化测试框架

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、什么是Selenium&#xff1f; Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供…

pytest教程-30-测试数据管理插件-pytest-datadir

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了pytest重复执行用例插件pytest-repeat&#xff0c;本小节我们讲解一下测试数据管理插件-pytest-datadir。 在软件测试中&#xff0c;有效管理测试数据对于编写全面的测试用例至关重要。Pytest…

Allure精通指南(04)静态和动态生成报告标记

文章目录 Allure 静态定制报告标记Allure 动态生成报告标记Allure 实现方式选择Allure 分类执行运行epic相关运行feature相关运行story相关运行story相关运行feature和多个story相关&#xff08;取并集&#xff09; Allure 静态定制报告标记 定义和用法&#xff1a; Decorators…

Learn ComputeShader 01 First Computer Shader

使用Unity版本&#xff1a;2019.4.12f1 整体流程&#xff1a; 1添加一个quad object并添加一个无光照材质 2.相机投影模式设置为正交 3.调整quad使其完全显示在相机内 4.创建脚本并且使用计算着色器覆盖quad的纹理 5.创建一个compute shader 前三步完成以后结果应该是这…

深入了解计算机系统——利用循环展开对程序的优化

系列文章&#xff1a; 操作系统详解(1)——操作系统的作用 操作系统详解(2)——异常处理(Exception) 操作系统详解(3)——进程、并发和并行 操作系统详解(4)——进程控制(fork, waitpid, sleep, execve) 操作系统详解(5)——信号(Signal) 文章目录 一些概念CPE 初步优化消除不必…
最新文章