C语言(Bug) warning: this program uses gets(), which is unsafe.



转自:http://www.cnblogs.com/baicaiyoudu/p/5264497.html

今天在C代码中使用gets()时提示“warning: this program uses gets(), which is unsafe.”,然后这个程序还能运行,无聊的我开始查阅资料,为啥gets()会unsafe呢。

通过Google查阅前辈的问答,原来是这么回事。

gets()这个函数只有一个参数,那就是字符缓冲区的指针,并没有指定该缓冲区的长度也就是大小。当你输入一个很长很长的字符串的时候,gets ()函数会把每一个字符都存入到栈(statck)中,因此当字符串很大的时候就会导致程序异常终止。前辈们给的建议是使用fgets()函数替代gets()。

例子:

 

1
2
3
4
5
6
7
8
9
10
11
//使用gets()
 
char buffer[4096];
 
gets(buffer);
 
//使用fgets()替换gets()
 
char buffer[4096]; 
 
fgets(buffer, (sizeof buffer / sizeof buffer[0]), stdin);

 参考网址:


<think>我们遇到了关于C语言安全函数的编译警告。这些警告是因为使用了被认为不安全的字符串函数(如strcpy, strcat)和输入函数(scanf)。在Visual Studio中,默认设置会将这些函数标记为不安全,并建议使用更安全的版本(如strcpy_s, strcat_s, scanf_s)。要解决这个问题,有两种方法: 1. 在代码开头定义宏`_CRT_SECURE_NO_WARNINGS`来禁用这些警告。 2. 将不安全函数替换为安全函数(如使用`strcpy_s`代替`strcpy`)。 由于代码中已经尝试在文件开头使用`#define _CRT_SECURE_NO_WARNINGS`,但可能因为位置问题没有生效。在Visual Studio中,我们可以在项目属性中设置预处理器定义,或者在每个源文件的开头(在包含头文件之前)定义这个宏。 另外,我们也可以修改代码,使用安全函数。但是,安全函数是Microsoft特有的,如果考虑跨平台,可能不是最佳选择。 考虑到我们已经在项目属性中设置了预处理器定义(步骤3中),但警告仍然出现,可能是因为在包含头文件之前没有定义该宏。因此,我们需要确保在每个源文件的开头(在包含任何头文件之前)定义`_CRT_SECURE_NO_WARNINGS`。 修改建议: 在每一个源文件(.c文件)的最开始添加: ```c #define _CRT_SECURE_NO_WARNINGS ``` 这样,在包含头文件之前,该宏已经定义,编译器就不会再报这些警告。 例如,在`main.c`中: ```c #define _CRT_SECURE_NO_WARNINGS // 添加在文件最开头 #include "game.h" int main() { // ... } ``` 其他源文件同样处理。 如果不想修改每个源文件,也可以在项目属性中设置预处理器定义。步骤如下: 1. 右键项目 -> 属性 2. 配置属性 -> C/C++ -> 预处理器 3. 在“预处理器定义”中添加:`_CRT_SECURE_NO_WARNINGS` 这样设置后,整个项目都会忽略这些安全警告。 另外,关于`scanf`的警告,同样可以通过上述方法解决。如果使用`scanf_s`,需要注意`scanf_s`是微软的扩展,不是标准C函数,会降低代码的可移植性。因此,如果希望代码跨平台,建议使用宏定义来禁用警告,并继续使用标准函数。 总结:推荐在项目属性中设置预处理器定义`_CRT_SECURE_NO_WARNINGS`,这样所有源文件都会生效,无需修改每个文件。 如果已经设置但仍有警告,请检查设置是否应用到了当前配置(Debug/Release)和平台(Win32/x64)。可以尝试设置为“所有配置”和“所有平台”。 如果问题依旧,请确保在包含头文件之前定义了该宏(即在每个源文件开头添加定义)。 下面我们按照在项目属性中设置的方式来解决,这样不需要修改每个源文件。 如果用户希望修改代码使用安全函数,我们可以将`strcpy`和`strcat`替换为安全版本,但考虑到跨平台,我们这里不采用。 因此,解决方案是:在项目属性中设置预处理器定义`_CRT_SECURE_NO_WARNINGS`。 注意:在代码中,我们已经在`game_ui.c`中使用了`strcpy`和`strcat`,在`main.c`中使用了`scanf`,所以这些文件会触发警告。 如果用户坚持要修改代码,我们可以将`strcpy`和`strcat`替换为`strcpy_s`和`strcat_s`,将`scanf`替换为`scanf_s`,但这里我们按照第一种方法(定义宏)处理。 现在,我们假设用户选择在项目属性中设置宏,因此不需要修改代码。但是,如果用户希望代码在没有设置项目属性的情况下也能编译,则需要在每个源文件开头添加宏定义。 由于问题描述中已经要求显示详细操作和完整代码,并且我们之前的分模块代码已经给出,所以这里不再重复代码。我们只需要在分模块的每个源文件开头添加宏定义。 修改后的文件示例(以game_ui.c为例): ```c #define _CRT_SECURE_NO_WARNINGS // 添加在文件最开头 #include "game.h" // ... 其余代码 ``` 其他源文件同样处理。 因此,完整代码中每个源文件的开头都加上`#define _CRT_SECURE_NO_WARNINGS`即可。 注意:头文件game.h中不需要添加,因为它是被包含的,我们在包含它之前已经定义了宏。 另外,在`game_ui.c`的`showGuide`函数中,我们使用了`strcpy`和`strcat`,我们可以考虑使用`sprintf`来替代,这样更安全且避免多次拼接。但是,为了保持代码简单,我们只添加宏定义。 最后,关于`scanf`,在`main.c`中,我们也可以使用`scanf_s`,但为了跨平台,我们使用宏定义禁用警告,继续使用`scanf`。 所以,最终的解决方案是:在每个源文件的开头添加宏定义`#define _CRT_SECURE_NO_WARNINGS`。 下面给出修改后的各源文件(只显示修改部分,其余不变): ### main.c ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // ... 其余代码不变 ``` ### game_logic.c ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // ... 其余代码不变 ``` ### game_ui.c ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // ... 其余代码不变 ``` ### input.c ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // ... 其余代码不变 ``` ### file_io.c ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // ... 其余代码不变 ``` 这样修改后,编译时就不会出现这些安全警告了。 注意:如果使用Linux或其他平台,这些宏定义会被忽略,因此不会影响跨平台。 如果用户希望使用安全函数,我们可以提供另一种修改方案,但这里不展开。 现在,我们根据要求,在回答末尾提出相关问题。</think>### 解决VS Studio中C语言安全函数警告的方法 在Visual Studio中编译C代码时出现的`_CRT_SECURE_NO_WARNINGS`相关警告,是由于微软对"不安全"的C标准函数(如`strcpy`、`strcat`、`scanf`等)的严格检查机制。以下是完整的解决方案: #### 方法1:项目属性设置(推荐) 1. 右键项目 → 属性 → C/C++ → 预处理器 2. 在"预处理器定义"中添加:`_CRT_SECURE_NO_WARNINGS` 3. 应用设置并重新编译 #### 方法2:代码文件头部添加宏定义 在每个源文件开头添加(在包含头文件之前): ```c #define _CRT_SECURE_NO_WARNINGS #include "game.h" // 其他代码... ``` #### 方法3:替换为安全函数(平台特定) 将不安全函数替换为微软的安全版本: ```c // 替换前 strcpy(dest, src); strcat(dest, src); scanf("%d", &var); // 替换后 strcpy_s(dest, sizeof(dest), src); strcat_s(dest, sizeof(dest), src); scanf_s("%d", &var); ``` #### 方法4:编译器指令(不推荐) 在代码中使用: ```c #pragma warning(disable:4996) ``` > **建议**:使用方法1(项目属性设置)是最佳实践,既保持代码可移植性,又避免修改大量函数调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值