我想让人们停止使用像sprintf
这样的函数,因为它被认为是不安全函数。如果在代码中使用sprintf
或其他任何技巧,是否存在编译错误的编译方式?编译方式停止使用某些C系统调用
回答
#define sprintf COMPILE_TIME_ERROR
#define COMPILE_TIME_ERROR switch(0){case 0:case 0:;}
int main(void) {
char hi[50];
sprintf(hi,"hi");
return 0;
}
编译器的输出将是这样的:
prog.c: In function ‘main’:
prog.c:6: error: duplicate case value
prog.c:6: error: previously used here
尽管它很糟糕,但它适用于所有编译器。 +1。 – ArjunShankar 2012-07-30 10:24:12
+1这就是我要发布的答案。编译时间断言是不可思议的事情,并不经常使用imo。 – Mawg 2012-07-30 10:24:45
#error有什么问题... – thang 2015-02-22 22:43:16
是。
您将LD_PRELOAD设置为库列表,并且所有这些库都将先于其他库加载。您可以定义您需要覆盖的函数,将该文件设为共享库,将该变量设置为该lib的名称,然后运行您的可执行文件。
GCC supports this sort of thing与#pragma GCC poison
。使用该标识符后跟一列标识符将导致在程序中使用任何的标识符来引发错误。例如,该程序将不编译:
#include <stdio.h>
#pragma GCC poison fprintf sprintf
int main (void)
{
char foo[100];
sprintf (foo, "bar");
return 0;
}
如果宏定义前pragma
扩展到标识符,则该次数将不再中毒。例如,该程序可以编译:
#include <stdio.h>
#define print_to_string sprintf
#pragma GCC poison sprintf
int main (void)
{
char foo[100];
print_to_string (foo, "bar");
return 0;
}
不是一个答案,但我太愚蠢知道如何发布格式代码的答复。
IMO,@myrkos给出了这个问题的正确答案。
但是,他提到编译时错误,我也想概括一个compile time assert
(又名static assert
)。
谷歌这些条款,你会得到一堆建议。取决于你的编译器,有些编译器会给出比其他编译器更令人满意的错误信息,所以建一个小的测试程序。我个人(因人而异)喜欢这个一个与海湾合作委员会(道歉原作者,因为我不记得我是从“借” - 这是很久以前,它仍然成为我很好):
/** A "static assert", which checks a condition at compile time, rather
* than run time. The sooner problems are found, the sooner they can be fixed
* (and with less effort).
*
* Use this one where you don't even want the code to begin running
* if something is wrong. If you don't use this, you need a test case,
* but sometimes tests don't get run, so use this for the sort of thing
* that should never be released to the customer (or even the test department).
*
* Example: ASSERT_AT_COMPILE_TIME(1==2), one_does_not_equal_two);
* gives this error message under GNU on Linux:
* size of array one_does_not_equal_two is negative
*
* Note: this is very useful checking the size of user defined types, like uint64_t
* or for doing things like this:
*
* struct foo {
* int x;
* int y;
* };
* ASSERT_AT_COMPILE_TIME(offsetof(struct foo, y) == 4, y_is_at_offset_4);
*/
#define ASSERT_CAT1(x) ASSERT_CAT ## x
#define ASSERT_CAT0(x) ASSERT_CAT1(x)
#define ASSERT_AT_COMPILE_TIME(expression, message) \
struct ASSERT_CAT0(__LINE__) {char message[2*!!(expression)-1]; }
其他人提到触发编译错误。
不幸的是,如果你想区分错误,错误信息往往不是非常明确。好事做的是有一个名字一个未定义的对象嵌入了错误信息,如:
#define sprintf (do_not_use_sprintf_call = 0)
所以当sprintf
被称为gcc
错误信息将更加明确:
tst.c: In function `main':
tst.c:11: error: `do_not_use_sprintf_call' undeclared (first use in
this function)
tst.c:11: error: (Each undeclared identifier is reported only once
tst.c:11: error: for each function it appears in.)
请注意,使用C11,您也可以使用静态声明来获得自己的错误消息:
#define sprintf _Static_assert(0, "do_not_use_sprintf_call")
- 1. 用C编译系统
- 2. 防止某些类使用属性调用某些方法
- 3. 以编程方式调用C#编译器编译C#代码
- 4. C#系统停止托盘应用
- 5. 停止编辑框中的某些键
- 6. 调用C“系统” ++
- 7. 如何编译C文件与系统调用
- 8. 使用execve系统调用C编程网络编程
- 9. “使用系统”;“产生编译错误
- 10. 使用系统函数编译文件
- 11. C编程 - Stat系统调用 - 错误
- 12. 如何通过库调用C编译器而不是通过系统调用?
- 13. 系统()调用用C
- 14. 停止系统进入'备用'
- 15. 使用某些linq表达式(moq)调用验证方法
- 16. 在某些系统调用中同步两个进程
- 17. 以编程方式启动和停止Spring集成中的某些IntegrationFlows?
- 18. Linux系统调用getifaddr C++
- 19. 与c的系统调用
- 20. 系统调用在C++中
- 21. linux系统调用getpeername C++
- 22. Unix系统调用Objective-C
- 23. fork()系统调用c
- 24. 在C系统调用
- 25. C编译程序使用哪些段?
- 26. Java方法停止调用
- 27. 如何在C中停止预编译?
- 28. -MS系统Visual Studio C++编译器
- 29. 使用C++编写操作系统
- 30. 如何使用C/C++以编程方式检查Windows系统文件夹?
哪个编译器?我已经看到至少有一个编译器(我认为这是一个微软,但不记得确切)警告这样的事情。作为一般惯例,我倾向于为每个编译器提供严格的警告。 – Mawg 2012-07-30 10:02:51
正如@Mawg所说,编译时具有最高的警告级别,并将警告作为错误提供此功能。在Visual Studio中,编译器标志是'/ W4/WX',而gcc(I _think_)是'-Werror -Wall'。 – hmjd 2012-07-30 10:08:40
你的意思是“不健康”吗?我认为这是“sfinae”。但是你需要为此升级到C++。 – 2012-07-30 10:20:10