LLDB 详解

LLDB 详解

  • LLDB 详解
    • 编译器集成优势
    • LLDB 的主要功能
    • 命令格式
      • 原始(raw)命令
      • 选项终止符: --
    • LLDB 中的变量
    • 唯一匹配原则
    • help
    • expression
    • print、call、po
    • 控制流程:continue、next、step、finish
    • register read / write
    • thread backtrace
    • thread return
    • frame 相关命令
    • breakpoint
      • 设置断点
      • 管理断点
      • 断点命令
    • watchpoint

LLDB 详解

LLDB,全称为Low-Level Debugger,是苹果公司开发的一款开源、高性能的源代码级调试器。作为Clang和LLVM项目的一部分,LLDB被设计为C、C++、Objective-C和Swift等编程语言的原生调试器。它提供了丰富的功能和灵活的接口,使得开发者能够有效地定位和修复代码中的错误。

编译器集成优势

LLDB将调试信息转换为Clang类型,以便利用Clang编译器基础设施。这允许LLDB在表达式中支持最新的C、C++、Objective-C语言功能和运行时,而无需重新实现任何此功能。它还利用编译器在使函数调用表达式、解码指令和提取指令详细信息等时处理所有ABI细节。

LLDB的主要优点有:

  1. C、C++、Objective-C的最新语言支持。
  2. 可以声明局部变量和类型的多行表达式。
  3. 当支持时,使用JIT作为表达式。
  4. 当无法使用JIT时,评估表达式中间表示(IR)。

LLDB 的主要功能

  • 断点设置:在特定的代码行或函数处设置断点,控制程序的执行流程。
  • 变量查看与修改:在运行时查看和修改变量的值,包括基本类型、结构体、类和数组等。
  • 内存查看:检查和修改内存内容,帮助理解程序的数据布局。
  • 线程和进程控制:管理线程和进程的执行状态,如暂停、继续、切换线程和终止进程。
  • 表达式计算:在调试环境中计算复杂的表达式,支持多种编程语言的语法。
  • 堆栈回溯:查看函数调用栈,追踪代码执行路径。
  • 插件支持:通过插件系统扩展LLDB的功能,以满足特定的调试需求。
  • 脚本编写:使用Python或Swift编写自定义调试脚本,自动化调试过程。

命令格式

<noun> <verb> [-option [option-value]] [argument [argument...]]
// [] 项为可选项
<命令> <子命令> [-选项 [选项值]] [参数 [参数值...]]

原始(raw)命令

LLDB支持不带命令选项(options)的原始(raw)命令,原始命令会将命令后面的所有东西当做参数(arguement)传递。不过很多原始命令也可以带命令选项,当你使用命令选项的时候,需要区分命令选项和参数。

常用的 expression 就是 raw 命令,一般情况下我们使用 expression 打印一个东西是这样的:

这里写图片描述

选项终止符: –

「选项」可以放在命令行的任何位置,但是如果参数以“-”开头,则必须通过添加选项终止符--来告诉 LLDB 你已经完成了当前命令的选项。

// 选项: -stop-at-entry, 参数:-program_arg
process launch --stop-at-entry -- -program_arg value

当我们想用 expression 打印一个对象的时候。需要使用 -O 命令选项,我们应该用 – 将命令选项和参数区分:

这里写图片描述

该命令可以简写为 po。

LLDB 中的变量

在 LLDB 中定义变量时,需要在变量前面添加$符号。定义好变量后就可以像平常一样使用变量,调用方法。方法调用时,LLDB 无法确定返回值的类型,需要自己指定。

// 定义变量array
(lldb) e NSArray *$array = @[@"I", @"love", @"LLDB"](lldb) po $array
<__NSArrayI 0x600000ffdb00>(
I,
love,
LLDB
)// 调用方法
(lldb) po [$array count]
3
(lldb) po [[$array objectAtIndex:1] uppercaseString]
LOVE(lldb) e int $b = 0
(lldb) po $b
0// 不指定返回值
(lldb) po [[$array objectAtIndex:$b] characterAtIndex:0]
0x0000000000000049// 指定返回值
(lldb) po (char)[[$array objectAtIndex:$b] characterAtIndex:0]
'I'

唯一匹配原则

LLDB的命令遵循唯一匹配原则:假如根据前n个字母已经能唯一匹配到某个命令,则只写前n个字母等效于写下完整的命令。利用该规则,可以简写一些命令。

help

好记性不如 help 命令。和平常的 pod --help ruby --help 不一样,LLDB help 本身是一个命令而不是一个选项,它可以告诉你关于某个命令(包括 help 命令)的一切信息。

(lldb) help
Debugger commands:apropos           -- List debugger commands related to a word or subject.breakpoint        -- Commands for operating on breakpoints (see 'help b' forshorthand.)command           -- Commands for managing custom LLDB commands.disassemble       -- Disassemble specified instructions in the currenttarget.  Defaults to the current function for thecurrent thread and stack frame.dwim-print        -- Print a variable or expression.expression        -- Evaluate an expression on the current thread.  Displaysany returned value with LLDB's default formatting.frame             -- Commands for selecting and examing the current thread'sstack frames.gdb-remote        -- Connect to a process via remote GDB server.If no host is specifed, localhost is assumed.gdb-remote is an abbreviation for 'process connect--plugin gdb-remote connect://<hostname>:<port>'gui               -- Switch into the curses based GUI mode.help              -- Show a list of all debugger commands, or give detailsabout a specific command.kdp-remote        -- Connect to a process via remote KDP server.If no UDP port is specified, port 41139 isassumed.kdp-remote is an abbreviation for 'process connect--plugin kdp-remote udp://<hostname>:<port>'language          -- Commands specific to a source language.log               -- Commands controlling LLDB internal logging.memory            -- Commands for operating on memory in the current targetprocess.platform          -- Commands to manage and create platforms.plugin            -- Commands for managing LLDB plugins.process           -- Commands for interacting with processes on the currentplatform.quit              -- Quit the LLDB debugger.register          -- Commands to access registers for the current thread andstack frame.script            -- Invoke the script interpreter with provided code anddisplay any results.  Start the interactive interpreterif no code is supplied.session           -- Commands controlling LLDB session.settings          -- Commands for managing LLDB settings.source            -- Commands for examining source code described by debuginformation for the current target process.statistics        -- Print statistics about a debugging sessionswift-healthcheck -- Provides logging related to the Swift expressionevaluator, including Swift compiler diagnostics. Thismakes it easier to identify project misconfigurationsthat result in module import failures in the debugger.The command is meant to be run after a expressionevaluator failure has occurred.target            -- Commands for operating on debugger targets.thread            -- Commands for operating on one or more threads in thecurrent process.trace             -- Commands for loading and using processor traceinformation.type              -- Commands for operating on the type system.version           -- Show the LLDB debugger version.watchpoint        -- Commands for operating on watchpoints.
Current command abbreviations (type 'help command alias' for more info):add-dsym  -- Add a debug symbol file to one of the target's current modulesby specifying a path to a debug symbols file or by using theoptions to specify a module.attach    -- Attach to process by ID or name.b         -- Set a breakpoint using one of several shorthand formats.bt        -- Show the current thread's call stack.  Any numeric argumentdisplays at most that many frames.  The argument 'all' displaysall threads.c         -- Continue execution of all threads in the current process.call      -- Evaluate an expression on the current thread.  Displays anyreturned value with LLDB's default formatting.continue  -- Continue execution of all threads in the current process.detach    -- Detach from the current target process.di        -- Disassemble specified instructions in the current target. Defaults to the current function for the current thread andstack frame.dis       -- Disassemble specified instructions in the current target. Defaults to the current function for the current thread andstack frame.display   -- Evaluate an expression at every stop (see 'help targetstop-hook'.)down      -- Select a newer stack frame.  Defaults to moving one frame, anumeric argument can specify an arbitrary number.env       -- Shorthand for viewing and setting environment variables.exit      -- Quit the LLDB debugger.f         -- Select the current stack frame by index from within the currentthread (see 'thread backtrace'.)file      -- Create a target using the argument as the main executable.finish    -- Finish executing the current stack frame and stop afterreturning.  Defaults to current thread unless specified.history   -- Dump the history of commands in this session.Commands in the history list can be run again using "!<INDEX>". "!-<OFFSET>" will re-run the command that is <OFFSET> commandsfrom the end of the list (counting the current command).image     -- Commands for accessing information for one or more targetmodules.j         -- Set the program counter to a new address.jump      -- Set the program counter to a new address.kill      -- Terminate the current target process.l         -- List relevant source code using one of several shorthand formats.list      -- List relevant source code using one of several shorthand formats.n         -- Source level single step, stepping over calls.  Defaults tocurrent thread unless specified.next      -- Source level single step, stepping over calls.  Defaults tocurrent thread unless specified.nexti     -- Instruction level single step, stepping over calls.  Defaults tocurrent thread unless specified.ni        -- Instruction level single step, stepping over calls.  Defaults tocurrent thread unless specified.p         -- Print a variable or expression.parray    -- parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION toget a typed-pointer-to-an-array in memory, and will displayCOUNT elements of that type from the array.po        -- Evaluate an expression on the current thread.  Displays anyreturned value with formatting controlled by the type's author.poarray   -- poarray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION toget the address of an array of COUNT objects in memory, and willcall po on them.print     -- Print a variable or expression.q         -- Quit the LLDB debugger.r         -- Launch the executable in the debugger.rbreak    -- Sets a breakpoint or set of breakpoints in the executable.re        -- Commands to access registers for the current thread and stackframe.repl      -- Evaluate an expression on the current thread.  Displays anyreturned value with LLDB's default formatting.run       -- Launch the executable in the debugger.s         -- Source level single step, stepping into calls.  Defaults tocurrent thread unless specified.shell     -- Run a shell command on the host.si        -- Instruction level single step, stepping into calls.  Defaults tocurrent thread unless specified.sif       -- Step through the current block, stopping if you step directlyinto a function whose name matches the TargetFunctionName.step      -- Source level single step, stepping into calls.  Defaults tocurrent thread unless specified.stepi     -- Instruction level single step, stepping into calls.  Defaults tocurrent thread unless specified.t         -- Change the currently selected thread.tbreak    -- Set a one-shot breakpoint using one of several shorthand formats.undisplay -- Stop displaying expression at every stop (specified by stop-hookindex.)up        -- Select an older stack frame.  Defaults to moving one frame, anumeric argument can specify an arbitrary number.v         -- Show variables for the current stack frame. Defaults to allarguments and local variables in scope. Names of argument,local, file static and file global variables can be specified.var       -- Show variables for the current stack frame. Defaults to allarguments and local variables in scope. Names of argument,local, file static and file global variables can be specified.vo        -- Show variables for the current stack frame. Defaults to allarguments and local variables in scope. Names of argument,local, file static and file global variables can be specified.x         -- Read from the memory of the current target process.
For more information on any command, type 'help <command-name>'.

expression

expression 命令的作用是执行一个表达式,并将表达式返回的结果输出。

  1. 执行某个表达式。 我们在代码运行过程中,可以通过执行某个表达式来动态改变程序运行的轨迹。 假如我们在运行过程中,突然想把 self.view 颜色改成红色,看看效果。我们不必写下代码,重新 run,只需暂停程序,用 expression 改变颜色,再刷新一下界面,就能看到效果。
(lldb) expression -- self.view.backgroundColor = [UIColor purpleColor];
(lldb) expression -- (void)[CAtransaction flush]
  1. 将返回值输出。 也就是说我们可以通过 expression 来打印东西。 假如我们想打印 self.view:
(lldb) expression -- self.view

print、call、po

一般情况下,我们直接用 expression 还是用得比较少的,更多时候我们用的是 print、call、po。这三个命令其实都是 expression 命令,执行某个表达式,并将执行的结果输出到控制台上。常用来动态调用方法,动态修改变量。

// 调用 description 进行打印
'call' is an abbreviation for 'expression --'
'print' is an abbreviation for 'expression --'

下面代码效果相同:

这里写图片描述

根据唯一匹配原则,如果你没有自己添加特殊的命令别名。e 也可以表示 expression 的意思,p 和 print 等价。

上面打印的都是指针,而不是对象本身。如果我们想打印对象,需要使用到命令选项:-O。为了更方便的使用,LLDB 为 expression -O 定义了一个别名:po。

// 调用 description 进行打印
'po' is an abbreviation for 'expression -O  --'

使用 po 指令动态修改变量:

// 背景颜色为 red
(lldb) po [self.view backgroundColor]
UIExtendedSRGBColorSpace 1 0 0 1
// 修改背景颜色为blue
(lldb) po [self.view setBackgroundColor:[UIColor blueColor]]
UICachedDeviceRGBColor
// 背景颜色发生改变
(lldb) po [self.view backgroundColor]
UIExtendedSRGBColorSpace 0 0 1 1
// 不用继续运行程序,马上进行渲染,模拟器/真机上也发生改变
(lldb) po [CATransaction flush]

控制流程:continue、next、step、finish

img

上图为 Xcode 里面的控制按键,其实都是与 LLDB 命令对应的,从左至右分别为:

  1. continue 按钮, 对应命令 process continue(简写 continuec),会取消程序的暂停,允许程序正常执行。
  2. step over 按钮,对应命令 thread step-over(简写 nextn),会以黑盒的方式执行一行代码。如果所在这行代码是一个函数调用,不会跳进这个函数,而是会执行这个函数,然后继续。
  3. step in 按钮,对应命令 thread step-in(简写 steps),如果所在这行代码是一个函数调用,会跳进这个函数,可用来调试或检查函数调用。当前行不是函数调用时,next 和 step 效果是一样的。
  4. step out 按钮,对应命令 thread step-out(简写 finish )。如果你不小心跳进一个函数,但实际上你想跳过它,可以用该命令跳出函数。

register read / write

寄存器指令,用来查看或修改系统库函数调用参数和返回值,寄存器与 CPU 架构有关。

(lldb) register read
General Purpose Registers:x0 = 0x000000010140a590x1 = 0x000000016f0ef2b0x2 = 0x0000000000000001x3 = 0x000000016f0ef578x4 = 0x0000000000000010x5 = 0x0000000000000620x6 = 0x0000000280ecc620x7 = 0x0000000000000000x8 = 0x0000000100d29000  (void *)0x0000000800000003x9 = 0x0000000201644dc0  dyld`_main_threadx10 = 0x0000000000000002x11 = 0x0000000101414488x12 = 0x0000000000000002x13 = 0x0000000000000000x14 = 0x0000000249680000x15 = 0x00000001a954f065  UIKitCore`_OBJC_$_INSTANCE_METHODS_UIViewController(UIAlertControllerContentViewController|UIResponderChainTraversal|UIActionSheetPresentationControllerAccess|UIImagePickerControllerAdditions|PLImagePickerViewControllerInterface|ForHomeOnly|UIPopoverController_Internal|_UIMultiColumnViewController|_UIKitIsUIViewController|UIPerformsActions|UITabBarControllerItem|UISplitViewController|BinaryCompatibility|UINavigationControllerItemInternal|UINavigationControllerItem|UINavigationControllerContextualToolbar|UINavigationControllerContextToolbar_Internal|UIContainerViewControllerProtectedMethods|UIContainerViewControllerCallbacks|UIContainerViewControllerCallbacks_Internal|StateRestoration_Internal|StateRestoration|ActivityContinuationPrivate|ActivityContinuationInternal|ActivityContinuation|EmbeddedViewSupport|UIFirstResponderSupport|UICollectionViewControllerSupport|UIViewControllerTransitioning|AdaptiveSizing|AdaptiveSizing_Internal|UIViewControllerClassDumpWarning|UIKeyCommand|ForUISplitViewController|AccessibilityHUD|OrientationDebugging|NSExtensionAdditionsInternal|NSExtensionAdditions|_UIApplicationRotationFollowing|_UIAlwaysOnEnvironment|_UIFallbackEnvironment|UnwindSegueSupport|_UISheetPresentationController|ViewServices|ViewService_Internal|ViewService_StateRestoration) + 1965x16 = 0x00000001a8861570  UIKitCore`-[UIViewController viewDidLoad]x17 = 0x0000000100e1dd4c  libMainThreadChecker.dylib`__trampolines + 18880x18 = 0x0000000000000000x19 = 0x000000010140ada0x20 = 0x000000010140a590x21 = 0x00000002016bb000  UIKitCore`UIKeyboardCachedIsRightHandDrivex22 = 0x0000000000000000x23 = 0x0000000000000000x24 = 0x0000000000000018x25 = 0x0000000000000000x26 = 0x0000000000000000x27 = 0x0000000000000460x28 = 0x0000000201694000  UIKitCore`_MergedGlobals + 4fp = 0x000000016f0ef410lr = 0x0000000100d10644  Landmarks`-[ViewController viewDidLoad] + 100 at ViewController.m:20:5sp = 0x000000016f0eed10pc = 0x0000000100d10648  Landmarks`-[ViewController viewDidLoad] + 104 at ViewController.m:23:6cpsr = 0x60000000

thread backtrace

有时候我们想要了解线程堆栈信息,可以使用 thread backtrace(简写为 bt),它的作用是将线程的堆栈打印出来。

这里写图片描述

thread return

thread return 可以接受一个表达式,调用命令之后直接从当前的 frame 返回表达式的值。

这里写图片描述

效果相当于在断点位置直接调用 return NO;,不会执行断点后面的代码。

frame 相关命令

  • frame variable:打印出当前 frame 的所有变量。

  • frame info:查看当前 frame 的信息。

  • frame select:选择某个 frame。

breakpoint

调试过程中,我们用得最多的可能就是断点了。LLDB 中的断点命令也非常强大。

设置断点

breakpoint set 命令用于设置断点,LLDB 提供了很多种设置断点的方式。

使用 -n 根据方法名设置断点:

// 给所有类中的 viewWillAppear: 设置一个断点
(lldb) breakpoint set -n viewWillAppear:

设置好断点后,会为该断点生成一个编号(id),从 1 开始递增。

使用 -f 指定文件:

// 给所有类中的 viewWillAppear: 设置一个断点
(lldb) breakpoint set -f ViewController.m -n viewDidLoad

使用 -l 指定文件某一行设置断点:

// 给 ViewController.m 第 38 行设置断点
(lldb) breakpoint set -f ViewController.m -l 38

使用 -c 设置条件断点:

//  text: 方法接受一个 ret 的参数,我们想让 ret == YES 的时候程序中断
(lldb) breakpoint set -n text: -c ret == YES

使用 -o 设置单次断点:

// 如果刚刚那个断点我们只想让它中断一次
(lldb) breakpoint set -n text: -o

管理断点

  • breakpoint list:查看已经设置了哪些断点。
  • breakpoint disable x:使 id 为 x 的断点暂时失效。
  • breakpoint enable x:使 id 为 x 的断点生效。
  • breakpoint delete x:删除 d 为 x 的断点。

断点命令

breakpoint command add 命令就是给断点添加命令的命令。

假设我们需要在 ViewController 的 viewDidLoad 中查看 self.view 的值,我们首先给 -[ViewController viewDidLoad] 添加一个断点。添加成功之后,这个断点的 id 为 3,然后我们给它增加一个命令:po self.view:

这里写图片描述

-o 完整写法是 –one-liner,表示增加一条命令。添加完命令之后,每次程序执行到这个断点就可以自动打印出 self.view 的值了。

如果我们想增加多条命令,我们可以输入 breakpoint command add 3,对断点 3 增加命令,输入 DONE 表示结束:

这里写图片描述

如果想查看某个断点已有的命令,可以使用 breakpoint command list。

// 查看 id 为 3 的断点已有的命令
breakpoint command list 3

breakpoint command delete 可以让我们删除某个断点的命令:

// 删除 id 为 3 的断点的所有命令
breakpoint command delete 3

watchpoint

breakpoint 有一个孪生兄弟 watchpoint。如果说 breakpoint 是对方法生效的断点,watchpoint 就是对地址生效的断点。我们可以用 watchpoint 观察这个属性的地址。如果地址里面的东西改变了,就让程序中断。

和 breakpoint 一样,watchpoint 也有 id。失效、生效、删除的语法也和 breakpoint 一致。

watchpoint set 命令用于添加一个 watchpoint。只要这个地址中的内容变化了,程序就会中断。一般情况下,要观察变量或者属性,使用 watchpoint set variable 命令即可:

// 观察 self->_string
watchpoint set variable self->_string

watchpoint set variable 传入的是变量名。需要注意的是,这里不接受方法,所以不能使用watchpoint set variable self.string,因为 self.string 调用的是 _string 的取方法。

给 watchpoint 添加命令的方法,和 breakpoint 完全一致,这里就不赘述了。

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

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

相关文章

精彩回顾 | 2024高通边缘智能创新应用大赛系列公开课

5月29日-6月6日&#xff0c;我们陆续开展了四场精彩绝伦的2024高通边缘智能创新应用大赛直播公开课。高通、阿加犀、广翼智联以及美格智能的业务领袖和行业大咖齐聚一堂&#xff0c;聚焦边缘智能&#xff0c;分享前沿技术、探讨创新应用&#xff0c;抢先揭秘比赛设备的核心特性…

MIT6.s081 2021 Lab System calls

xv6系统调用实现 不同于 Lab1 利用已实现的系统调用来实现一些用户态下的命令行程序&#xff0c;本 Lab 是要在内核层面实现一些系统调用。这其中难免涉及到一些对内核数据结构的操作&#xff0c;以及处理器体系结构&#xff08;本系列 Lab 基于 RISCV&#xff09;相关的内容&…

什么是慢查询——Java全栈知识(26)

1、什么是慢查询 慢查询&#xff1a;也就是接口压测响应时间过长&#xff0c;页面加载时间过长的查询 原因可能如下&#xff1a; 1、聚合查询 2、多表查询 3、单表数据量过大 4、深度分页查询&#xff08;limit&#xff09; 如何定位慢查询&#xff1f; 1、Skywalking 我们…

IND83081芯片介绍(一)

一、芯片介绍 IND83081是indiemicro推出的一款高性能的汽车矩阵LED照明控制器&#xff0c;集成了四个子模块&#xff0c;每个子模块包含三个串联的MOSFET开关&#xff0c;每个开关均可通过12位PWM内部信号控制&#xff0c;可配置的上升和下降速率及相位移以实现精确控制&#x…

JOSEF约瑟 JOXL-J拉绳开关 整定范围宽

用途 双向拉绳开关的壳体采用金属材料铸造&#xff0c;具有足够的机械强度,抵抗并下工作时脱落的岩石&#xff0c;爆块等物体的撞击不被破坏&#xff0c;当胶带输送机发生紧急事故时&#xff0c;启动拉绳开关,可立即停机报警&#xff0c;防止事故的扩大,保证工作现场的人身安全…

java 操作 milvus 2.1.4

1. 确认 docker 运行的 milvus容器镜像版本情况&#xff1a; 2. pom 依赖&#xff1a; <dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.1.0</version><exclusions><exclusi…

Java学习 - Redis慢查询与发布订阅与流水线

慢查询 慢查询是什么 慢查询本质是慢查询日志&#xff0c;它记录了一些执行速度很慢的命令 慢查询与生命周期 生命周期 ------- ------------------------------------------ | | 1.发送请求 | redis服务端 …

Simulink缓存文件有什么用?

在使用Simulink进行仿真的过程中&#xff0c;经常会发现目录下存在一些后缀为.slxc的文件&#xff0c;这些其实就是Simulink模型的缓存文件&#xff08;.slx cache&#xff09;。 Simulink缓存文件的主要作用是提高仿真和代码生成的效率。 借助缓存文件&#xff0c;可以避免…

Web浏览器读写NFC Ntag标签

本示例使用的发卡器&#xff1a;RS232串口USB转COM读写器IC卡发卡器WEB浏览器二次开发JS编程SDK-淘宝网 (taobao.com) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&g…

不锈钢氩弧焊丝ER316L

说明&#xff1a;TG316L 是超低碳的不锈钢焊丝。熔敷金属耐蚀、耐热、抗裂性能优良。防腐蚀性能良好。 用途:用于石油化工、化肥设备等。也可用于要求焊接后不进行热处理的高Cr钢的焊接。

真实评测:可道云teamOS文件上传功能丝滑到爱不释手

对于每日沉浸在图片与视频海洋中的媒体工作者而言&#xff0c;与海量的多媒体文件打交道几乎成了家常便饭。 文件的上传和存储&#xff0c;对他们而言&#xff0c;不仅仅是工作中的一个环节&#xff0c;更像是将一天的辛勤与付出妥善安置的仪式。无论是突发现场的精彩瞬间&am…

海报在线制作系统源码小程序

轻松设计&#xff0c;创意无限 一款基于ThinkPHPFastAdminUniApp开发的海报在线制作系统&#xff0c; 本系统不包含演示站中的素材模板资源。​ 一、引言&#xff1a;设计新纪元&#xff0c;在线海报制作引领潮流 在数字时代&#xff0c;海报已成为传播信息、展示创意的重要媒…

配音软件哪个好用?推荐5款智能配音软件

随着期末考来袭&#xff0c;校园里的空气似乎都凝固了&#xff0c;每个角落都充满了紧张的气氛。 然而&#xff0c;在这紧张的氛围中&#xff0c;有一群学生却显得格外从容&#xff0c;因为他们掌握了一种秘密武器——配音软件。这些软件就像是他们的个人学习助理&#xff0c;…

git 中有关 old mode 100644、new mode 10075的问题解决小结

问题&#xff1a; 同一个文件被修改后&#xff0c;最后代码没有变&#xff0c;文件变了&#xff0c;导致提交了一个空文件 git diff 提示 filemode 发生改变&#xff08;old mode 100644、new mode 10075&#xff09; 解决办法 &#xff1a; 原来是 filemode 的变化&#xff…

虚拟机字节码执行引擎之运行时栈帧结构

概述 执行引擎是Java虚拟机核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地定…

彩虹PLM系统:引领汽车行业的数字化转型

彩虹PLM系统&#xff1a;引领汽车行业的数字化转型 彩虹PLM系统作为汽车行业数字化转型的引领者&#xff0c;凭借其卓越的技术实力和丰富的行业经验&#xff0c;为汽车行业带来了全面的解决方案。以下是彩虹PLM系统如何引领汽车行业数字化转型的详细分析&#xff1a; 一、整合全…

约课健身管理系统小程序源码

健身达人的智能助手 一款基于FastAdminThinkPHPUniapp开发的米扬约课健身管理系统&#xff0c;应用于健身房&#xff0c;健身工作室&#xff0c;运动会所&#xff0c;运动场馆&#xff0c;瑜伽馆&#xff0c;拳馆等泛健身行业的场馆中。米扬约课健身致力于为各种健身场馆打造真…

Verilog刷题笔记49——Fsm1同步复位

题目&#xff1a; 解题&#xff1a; module top_module(clk,reset,in,out);input clk;input reset;input in;output out;parameter A0,B1;reg [1:0]current_state,next_state;always(posedge clk)beginif(reset)current_stateB;elsecurrent_statenext_state;endalways(*)beg…

手机图片怎么上传到电脑记事本 保姆级教程

在这个数字化时代&#xff0c;手机成了我们随身携带的摄影棚。无论是旅途中的美景&#xff0c;还是与朋友欢聚的瞬间&#xff0c;手机总能轻松捕捉。然而&#xff0c;手机存储空间有限&#xff0c;那些珍贵的照片和视频&#xff0c;怎样才能安全又方便地保存下来&#xff0c;供…

PFA量杯:精确、实用、高颜值的量杯选择!

您是否在烹饪、实验室实验或日常使用中需要一个精确、实用且高颜值的量杯&#xff1f;PFA量杯是您最佳的选择&#xff01; PFA量杯采用高品质材料制成&#xff0c;具有良好的耐腐蚀性、耐高温性&#xff0c;使用寿命长。透明度极高的杯身&#xff0c;使您在使用时能够清晰地看…