[英]C warnings a concern at runtime?
使用VS 2003构建的用于生成32位二进制文件的代码是在没有任何警告的情况下构建的。
相同的代码,无需更改单个代码,即可使用Visual Studio 2010编译器成功生成带有以下警告列表的64位二进制BUT,从而进行编译和链接。
因此,我的问题是,下面列出的任何警告在运行时是否值得关注?
pcd.c(248) : warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
pcd.c(377) : warning C4244: '=' : conversion from 'uintptr_t' to 'ULONG', possible loss of data
pcd.c(236) : warning C4100: 'argv' : unreferenced formal parameter
i.c(183) : warning C4100: 'lpReserved' : unreferenced formal parameter
api.c(506) : warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details.
api.c(554) : warning C4310: cast truncates constant value
api.c(719) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
api.c(2217) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
api.c(2892) : warning C4312: 'type cast' : conversion from 'ULONG_T' to 'HANDLE_T' of greater size
api.c(559) : warning C4702: unreachable code
stdio.h(234) : see declaration of 'fopen'
api.c(2217) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
prm.c(681) : warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\stdio.h(234) : see declaration of 'fopen'
host.c(410) : warning C4311: 'type cast' : pointer truncation from 'PVOID_T' to 'unsigned long'
stub.c(138) : warning C4295: 'eye' : array is too small to include a terminating null character
isv.c(372) : warning C4310: cast truncates constant value
chp.c(250) : warning C4244: '=' : conversion from 'SOCKET' to 'ULONG_T', possible loss of data
api.c(665) : warning C4311: 'type cast' : pointer truncation from 'HANDLE_T' to 'LONG'
api.c(1216) : warning C4057: 'function' : 'LPDWORD' differs in indirection to slightly different base types from 'LONG_T *'
hlp.c(1171) : warning C4057: 'function' : 'LPDWORD' differs in indirection to slightly different base types from 'LONG_T *'
neto.c(435) : warning C4057: 'function' : 'PLONG_T' differs in indirection to slightly different base types from 'ULONG_T *'
neto.c(595) : warning C4152: nonstandard extension, function/data pointer conversion in expression
neto.c(2115) : warning C4213: nonstandard extension used : cast on l-value
neto.c(2209) : warning C4057: 'function' : 'int *' differs in indirection to slightly different base types from 'LONG *'
td.c(760) : warning C4244: '=' : conversion from 'uintptr_t' to 'int', possible loss of data
td.c(2104) : warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'PVOID'
msc.c(287) : warning C4133: 'function' : incompatible types - from 'long *' to 'time_t *'
msc.c(1009) : warning C4702: unreachable code
inf.c(400) : warning C4057: 'function' : 'PLONG_T' differs in indirection to slightly different base types from 'ULONG *'
arb.c(166) : warning C4267: '=' : conversion from 'size_t' to 'LONG_T', possible loss of data
arb.c(226) : warning C4244: '=' : conversion from 'int' to 'CHAR_T', possible loss of data
sl.c(441) : warning C4054: 'type cast' : from function pointer 'int (__cdecl *)(unsigned char *,int,int,void *)' to data pointer 'void *'
pco.c(369) : warning C4057: 'function' : 'PLONG_T' differs in indirection to slightly different base types from 'ULONG_T *'
exit1.c(157) : warning C4295: 'publickey' : array is too small to include a terminating null
env.c(341) : warning C4267: 'function' : conversion from 'size_t' to 'DWORD', possible loss of data
hook.c(221) : warning C4245: 'return' : conversion from 'int' to 'SOCKET', signed/unsigned mismatch
hook.c(817) : warning C4311: 'type cast' : pointer truncation from 'unsigned char *' to 'int'
tor.c(128) : warning C4244: 'function' : conversion from 'time_t' to 'unsigned int', possible loss of data
cth.c(1012) : warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data
cntrl.c(427) : warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
api.c(263) : warning C4057: 'function' : 'int *' differs in indirection to slightly different base types from 'LONG_T *'
api.c(706) : warning C4057: 'function' : 'int *' differs in indirection to slightly different base types from 'DWORD *'
ii.c(252) : warning C4244: '=' : conversion from 'time_t' to 'long', possible loss of data
谢谢
我建议您只是在阅读错误消息方面变得更好。 它们用简单的语言编写。 您可以使用Google尚未理解的术语。
让我们经过一堆,好吗?
pcd.c(248):警告C4996:'getenv':此函数或变量可能不安全。 考虑改用_dupenv_s。 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 详细信息请参见在线帮助。
仅当您在更改另一个线程的变量时调用getenv
时,我才会为此担心。 这些例程的问题在于它们依赖于全局状态,当使用多个线程时,这会成为问题。 较新的版本也更清楚谁拥有什么分配。
pcd.c(377):警告C4244:'=':从'uintptr_t'转换为'ULONG',可能丢失数据
看起来可疑。 您是否正在通过将指针转换为整数来做一些时髦的事情? 在引入64位Windows时,他们为此添加了ULONG_PTR
。
pcd.c(236):警告C4100:'argv':未引用的形式参数
ic(183):警告C4100:'lpReserved':未引用的形式参数
可以安全地忽略或抑制。
api.c(506):警告C4996:'stricmp':此项的POSIX名称已弃用。 而是使用符合ISO C ++的名称:_stricmp。 详细信息请参见在线帮助。
不十分担心。 带下划线的名称可能最终使您无法使用* nix系统。
api.c(554):警告C4310:强制截断常量值
看起来可疑。 请提供示例。
api.c(719):警告C4996:'strcpy':该函数或变量可能不安全。 考虑改用strcpy_s。 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 详细信息请参见在线帮助。
api.c(2217):警告C4996:'sprintf':此函数或变量可能不安全。 考虑改用sprintf_s。 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 详细信息请参见在线帮助。
这些是每个体面的C程序员都应了解或理解的古老问题。 请进行谷歌搜索或一些有关缓冲区溢出的信息,以及为什么应尽可能避免使用这些功能。 请注意,尽管_s
名称在C1x标准中,但它们在* nix系统上可能不太常见。 还有符合旧标准的snprintf
和strncpy
。
api.c(2892):警告C4312:“类型转换”:从“ ULONG_T”到更大尺寸的“ HANDLE_T”的转换
不确定HANDLE_T
是什么,但是在Win32中, HANDLE
是指针的大小。 这很糟糕。 我建议像以前一样使用ULONG_PTR
。
api.c(559):警告C4702:无法访问的代码
确切地说。
stdio.h(234):参见'fopen'的声明
你看见了吗?
api.c(2217):警告C4996:'sprintf':此函数或变量可能不安全。 考虑改用sprintf_s。 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 详细信息请参见在线帮助。
与上面类似。
prm.c(681):警告C4996:'fopen':该函数或变量可能不安全。 考虑改用fopen_s。 要禁用弃用,请使用_CRT_SECURE_NO_WARNINGS。 详细信息请参见在线帮助。 C:\\ Program Files(x86)\\ Microsoft Visual Studio 10.0 \\ VC \\ INCLUDE \\ stdio.h(234):请参见'fopen'的声明
这是MS编译器开始推荐的另一个C11功能。 这是一种怀疑。 fopen
可能还可以。 阅读相应的文档。
host.c(410):警告C4311:'type cast':指针从'PVOID_T'到'unsigned long'的截断
使用ULONG_PTR
或uintptr_t
而不是unsigned long
。
stub.c(138):警告C4295:'eye':数组太小,无法包含终止的空字符
我的猜测是您声明了这样的字符串:
char foo[n] = "blah";
其中n
的大小太小而无法容纳字符串。 只需删除整数。
api.c(1216):警告C4057:'功能':'LPDWORD'的间接寻址方式与'LONG_T *'略有不同
DWORD
和LONG
是不同的类型,您正在使用指向一个的指针并将其用作另一个。 这是非法的。 (在这种情况下,它不会给您带来问题,但是您应该修复它。)
neto.c(595):警告C4152:非标准扩展,表达式中的函数/数据指针转换
嗯,不知道你是怎么做到的。 也许您将函数指针分配给void *
? 尽管从标准上讲,这在技术上是非法的,但是有几个库需要这样做。
neto.c(2115):警告C4213:使用了非标准扩展名:在L值上强制转换
我的猜测是您做了这样的事情:
*(char*)foo = bar;
非法。
neto.c(2209):警告C4057:'function':'int *'的间接寻址方式与'LONG *'略有不同
与交替使用PDWORD
和LONG
相似的情况。
td.c(2104):警告C4054:“类型转换”:从函数指针“ FARPROC”到数据指针“ PVOID”
与neto.c类似,第595行。
是:
我看到有几种会导致未定义行为的原因。
所有警告均应被视为逻辑错误(至少在您的考虑范围内),并应加以注意并使其保持沉默。 通过显式地更改代码/通过使用编译器指令来使警告静音(然后写一长串关于为何使警告静音的注释,这也表明它已被故意考虑)。
快速检查我首先要检查的内容(删除重复项)。
这些绝对听起来很糟糕:
stub.c(138) : warning C4295: 'eye' : array is too small to include a terminating null character
exit1.c(157) : warning C4295: 'publickey' : array is too small to include a terminating null
这些可能是不好的:
api.c(554) : warning C4310: cast truncates constant value
chp.c(250) : warning C4244: '=' : conversion from 'SOCKET' to 'ULONG_T', possible loss of data
api.c(1216) : warning C4057: 'function' : 'LPDWORD' differs in indirection to slightly different base types from 'LONG_T *'
neto.c(2209) : warning C4057: 'function' : 'int *' differs in indirection to slightly different base types from 'LONG *'
td.c(760) : warning C4244: '=' : conversion from 'uintptr_t' to 'int', possible loss of data
msc.c(287) : warning C4133: 'function' : incompatible types - from 'long *' to 'time_t *'
arb.c(166) : warning C4267: '=' : conversion from 'size_t' to 'LONG_T', possible loss of data
arb.c(226) : warning C4244: '=' : conversion from 'int' to 'CHAR_T', possible loss of data
api.c(665) : warning C4311: 'type cast' : pointer truncation from 'HANDLE_T' to 'LONG'
这些我不会留在代码中,但可能是良性的:
api.c(559) : warning C4702: unreachable code
td.c(2104) : warning C4054: 'type cast' : from function pointer 'FARPROC' to data pointer 'PVOID'
有三种警告:
有关不安全/不推荐使用的功能的警告。 您可能以前已经收到过一些警告,因为这些功能不安全/不标准,并且以前可能已弃用。 但是,如果您对它们有所了解并确保正确使用它们(请记住,某些类型的大小会以64位更改),则可以继续使用它们。 但是,我会尽量使用标准功能。 如果您确定正确使用功能,则至少应分别关闭警告。
以前也应该存在的警告,例如“未引用的参数”,带符号/无符号的不匹配,无法访问的代码以及诸如警告C4295,C4054,C4133之类的讨厌的东西。 您应该修复所有这些。 有些不是很严重(例如,有符号/无符号不匹配),但也很容易修复,因此修复它们只是使编译器静音。
在具有MSVC的Windows上64位大小不同引起的警告。 在32位中,int,long,long long,指针,size_t等具有32位大小。 您可以无缝转换它们,而不会丢失数据。 但是,在64位中,long long,size_t和指针具有64位大小,而long和int仍为32位。 转换它们可能会丢失信息,尤其是在涉及指针的情况下。 尝试使用正确的类型,不要使用缩小转换。 这也适用于这些类型的各种typedef,例如PVOID,DWORD以及WinAPI用来为同一事物指定其他名称的所有这些typedef。
通常:出现警告是有原因的。 通过注意每个警告并对代码进行适当的更改,尝试使编译器尽可能地静音。 如果您绝对必须进行转换并且确定它们不会影响程序的有效性,请使用显式强制转换(在大多数情况下,即static_cast
)。 这样,您可以确保不会错过提示真正愚蠢错误的单个警告,您将有一天会彻底破坏整个程序,并且要经过漫长的调试才能发现。 我知道这很乏味,尤其是在32/64位双平台编译上,但从长期来看,值得这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.