最近编写一个非常简单的代码,遇到奇怪的问题,有兴趣的朋友可以先自己猜一下,答案在后面。
代码如下:
/** @file A simple, basic, application showing how the Hello application could be built using the "Standard C Libraries" from StdLib. Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include <Library/BaseLib.h> #include <Uefi.h> #include <Library/UefiLib.h> #include <Library/PrintLib.h> #include <Library/ShellCEntryLib.h> #include <Protocol/EfiShell.h> #include <Library/ShellLib.h> void prt(IN UINT16 *p) { UINT8 i; for (i=0;i<256;i++) { Print(L"%c",*p); p++; } } INTN EFIAPI ShellAppMain ( IN UINTN Argc, IN CHAR16 **Argv ) { CHAR8 buffer[256]; UINT16 i; for (i=0;i<256;i++) { buffer[i]='L'; } prt((UINT16*)buffer); return 0; }
错误信息如下:
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\x86_amd64\li
b.exe" /NOLOGO /LTCG /OUT:d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\App
lications\SimpleDemo\SimpleDemo\OUTPUT\wft.lib @d:\udk2017\Build\AppPkg\DEBUG_VS
2013x86\X64\AppPkg\Applications\SimpleDemo\SimpleDemo\OUTPUT\object_files.lst
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\x86_amd64\li
nk.exe" /OUT:d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\Sim
pleDemo\SimpleDemo\DEBUG\wft.dll /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OP
T:ICF=10 /MAP /ALIGN:32 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /
DLL /ENTRY:_ModuleEntryPoint /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BAS
E:0 /DRIVER /DEBUG @d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applicat
ions\SimpleDemo\SimpleDemo\OUTPUT\static_library_files.lst
Generating code
Finished generating code
UefiApplicationEntryPoint.lib(ApplicationEntryPoint.obj) : error LNK2001: unreso
lved external symbol memset
d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\SimpleDemo\Simpl
eDemo\DEBUG\wft.dll : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 12.0
\Vc\bin\x86_amd64\link.exe"' : return code '0x460'
Stop.
build...
: error 7000: Failed to execute command
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Vc\bin\nmake.exe /no
logo tbuild [d:\udk2017\Build\AppPkg\DEBUG_VS2013x86\X64\AppPkg\Applications\Sim
pleDemo\SimpleDemo]
build...
: error F002: Failed to build module
d:\udk2017\AppPkg\Applications\SimpleDemo\SimpleDemo.inf [X64, VS2013x86
, DEBUG]
- Failed -
Build end time: 11:17:59, Dec.12 2017
Build total time: 00:00:12
上面就是完整的代码和现象,有兴趣的朋友可以琢磨一下,答案在下面。
刚开始看到错误提示我还非常疑惑”为啥没有具体错误信息“。仔细观察才发现错误信息是无法Link到 memset上。但是我的代码没有调用 memset。带着疑惑,我在 Inf 中刚加入 /FAcs /Od 准备查看汇编级代码。但是加入之后错误就会消失。
[BuildOptions]
MSFT:*_*_X64_CC_FLAGS = /FAcs /Od
再仔细研究,原来是 /Od 会让错误消失,接下来就简单了,比较只有 /FAcs 和带有 /Od的汇编代码,在 Simpledemo.cod 文件中找到了答案。左边是没有加入 /Od 的,右边是加入 /Od 的。这个参数的意思是关闭优化。比较打开和关闭优化的结果:
因此,问题就清楚了,因为我的赋值是对 buffer[] 全部写入 “L”,所以编译器会自作主张的用memset 来对内存直接赋值,但是恰好我们没有定义 memset,所以就会出现错误。
這問題剛好之前遇到 ,之前百思不得其解
那時最後for迴圈還改寫成 每個array值一一給予
感謝版主 現在懂了
前两天 手贱的写了个 CHAR8 *buffer[256] = {0}; 也是这个错误。
你有没有换VS2015试试呢?
好像VS2015内置了memset
我用的就是 vs2015 。 我记得之前看过 uefi 的编译设置,会设定“不使用编译器自带的库”,所以即使 vs 自定义了 memset 也是不会使用的。
那请问最后是怎么解决的呢,是编译时候加上/Od吗。
可以用C 库函数直接赋值,而不是用for 来填充。再或者将 memset 函数头文件Include进去就不会找不到了。
include 头文件有用吗?照理来说这是 link 阶段发生的事情,头文件里面应该只是一些宏和函数原型,生成的 obj 文件里面似乎不会提示哪些库被用到?
你说的对,是 link 阶段的问题,对于 edk2 来说加入适当的 lib 就可以了
最近看了一些memory function的源码,有些地方是这样描述的:
//
// Declare the local variables that actually move the data elements as
// volatile to prevent the optimizer from replacing this function with
// the intrinsic memset()
//
volatile UINT8 *Pointer;
变量声明volatile, 以防止这种情形的典范,有好几处都是这样子描述的,大伙可以搜一下。
哦哦 这样啊,谢谢,回头研究一下
为什么我变量加了volatile,后会提示warning C4090: 'function' : different 'volatile' qualifiers
贴上来完整的代码我看看?