我正在运行OS X Sierra,并试图编译一个使用strcpy_s
的c程序,但我安装的clang编译器使用的是c99标准,而from what I've read strcpy_s需要c11。
这是我要编译的代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
这是我用来编译的命令
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我试过用标准标志编译...clang -std=c11 copytest.c -o copytest
个
但是我得到了同样的“invalidinc99”警告。我也尝试过用gcc编译,但是仍然得到同样的c99警告。
我尝试通过自制软件升级,显示如下
警告:gcc 9.2.0已安装并且是最新的
我有clang版本9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
我的xcode版本是Xcode 9.2,从我所读到的一切来看,它应该带有c11支持。
我在编译时做错了什么吗?我的代码本身不正确吗?This是我在这里找到的唯一一个类似的问题,但它甚至没有答案。谢谢
2条答案
按热度按时间qkf9rpyu1#
_s
函数是2011 C标准的一个 * 可选 * 组件(附件K),而据本人所知,它们从未被实现为任何C库的一个集成部分。2可移植代码不能依赖于它们的可用性。(Microsoft的Windows版C编译器实现了一组重叠的函数,这些函数具有相同的名称但语义不同(并且至少存在一个bolt-on implementation。See this old answer, and the much longer question and answer it links to, for more detail。)此外,
_s
函数没有解决它们本来要解决的问题(不安全的字符串处理);有必要对每次使用strcpy
进行适当的修复,而不是像附录K的作者所希望的那样,全局搜索strcpy
并将其替换为strcpy_s
等。如果您确实对适当的修复进行了适当的思考,那么您将不需要任何_s
函数来实现它。例如,下面是示例程序修复版本:这里有一个更好的版本:
因此:永远不要使用任何
_s
函数。如果你需要编写一个在Windows上编译而没有警告的程序,把#define _CRT_SECURE_NO_WARNINGS 1
放在每个文件的顶部,这样MSVC就不会给你不好的建议。7kqas0il2#
如果所有的程序员,甚至大多数程序员一直都在写上面建议的解决方案,那么这些函数就不需要了。我们有很多证据表明,许多程序员没有写这样仔细的代码,可以追溯到Spaf在20世纪80年代末对Robert T Morris手指蠕虫的注解。
您也不希望为strcpy的每个调用点重复10行代码。这会导致代码不可读。更重要的是,zwol建议的实际上只是他声称我们不需要的函数的一个实现。一个好的程序员会接受它,把它放在一个头中,并给它起一个有用的名字,也许是checked_strcpy?或者甚至是strcpy_s?
第二个建议的实现,据说更好,但不是--它会在我们已经有缓冲区的时候导致分配。分配是昂贵的,在任何地方使用这种方法都会对perf不利。它还引入了新的复杂性,因为现在我们必须释放每个重复的字符串--想象一下重复调用strcat来做这件事。
这里有一个非常好的跨平台实现:https://github.com/intel/safestringlib
我也不确定这是否真的有什么不同,但值得一看-https://github.com/coruus/safeclib