最近编写代码的时候,忽然提出一个问题,按照下面的写法会导致内存泄漏的问题吗?
for (UINTN i=0;i<1000;i++) {
UINTN x;
Print(L"%x\n",x++);
}
为了验证这个,编写一个完整的 UEFI 代码进行测试:
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
/***
Print a welcoming message.
Establishes the main structure of the application.
@retval 0 The application exited normally.
@retval Other An error occurred.
***/
INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
for (UINTN i=0;i<1000;i++) {
UINTN x;
Print(L"%x\n",x++);
}
return(0);
}
对应的,在 INF 文件中定义生成汇编代码:
[BuildOptions]
MSFT:*_*_X64_CC_FLAGS = /FAsc /Od
查看生成的 cod文件:
$LN6:
00000 48 89 54 24 10 mov QWORD PTR [rsp+16], rdx
00005 48 89 4c 24 08 mov QWORD PTR [rsp+8], rcx
0000a 48 83 ec 48 sub rsp, 72 ; 00000048H
; 27 :
; 28 : for (UINTN i=0;i<1000;i++) {
0000e 48 c7 44 24 20
00 00 00 00 mov QWORD PTR i$1[rsp], 0
00017 eb 0d jmp SHORT $LN4@ShellAppMa
$LN2@ShellAppMa:
00019 48 8b 44 24 20 mov rax, QWORD PTR i$1[rsp]
0001e 48 ff c0 inc rax
00021 48 89 44 24 20 mov QWORD PTR i$1[rsp], rax
$LN4@ShellAppMa:
00026 48 81 7c 24 20
e8 03 00 00 cmp QWORD PTR i$1[rsp], 1000 ; 000003e8H
0002f 73 2a jae SHORT $LN3@ShellAppMa
; 29 : UINTN x;
; 30 : Print(L"%x\n",x++);
00031 48 8b 44 24 28 mov rax, QWORD PTR x$2[rsp]
00036 48 89 44 24 30 mov QWORD PTR tv68[rsp], rax
0003b 48 8b 54 24 30 mov rdx, QWORD PTR tv68[rsp]
00040 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_17KDIHCDGM@?$AA?$CF?$AAx?$AA?6@
00047 e8 00 00 00 00 call Print
0004c 48 8b 44 24 28 mov rax, QWORD PTR x$2[rsp]
00051 48 ff c0 inc rax
00054 48 89 44 24 28 mov QWORD PTR x$2[rsp], rax
; 31 : }
00059 eb be jmp SHORT $LN2@ShellAppMa
$LN3@ShellAppMa:
可以看到:变量 X 就是 QWORD PTR i$1[rsp],在循环中并不会每次重新分配内存。因此,无需担心内存泄漏的问题。
查了一下资料:
“在C语言的早期版本中,局部变量的声明必须集中在函数或代码块的开头,位于任何可执行语句之前。这种限制在C89/ANSI C标准中得到了明确的规范。
随着C语言标准的发展,C99标准引入了更灵活的变量声明方式,允许在代码块的任意位置声明局部变量,只要遵循“先定义后使用”的原则即可。这种改进使得程序员可以在需要使用变量的地方才进行声明,从而提高了代码的可读性和编写灵活性。“