问题:彻底无语了,不小心某个文件包含了windows.h头文件,而windows.h文件里面包含着winsock.h文件,
如果你下次使用winsock2.h文件时,位置不对,然后编译器会给你一大堆重定义错误问题。
初级解决办法:
把winsock2.h文件放在任何可能包含winsock.h文件(尤其是windows.h文件,它就包含了winsock.h文件)的前面,因为winsock2.h头文件有这样的宏定义:
#ifndef _WINSOCK2API_
#define _WINSOCK2API_
#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
如果在winsock2.h之后再引用winsock.h头文件,那么winsock.h文件并没有什么卵用。
在生成应用程序时,即使不是MFC应用程序,也有有这个东西:
而网上对stdafx.h文件的解释是:把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
可怕的是它包含了windows.h文件,然而并不可怕的是:当我们使用AppWizard来自动生成某些项目的时候,系统会自动把所需要include的头文件在stdafx.h中先include一下,这样,我们只需要直接include这个stdafx.h文件即可。只在使用AppWizard来自动生成项目的时候,才出现.否则,就没有必要include此头文件stdafx.h了。参考网页。
所以如果是MFC等windows窗口项目,需要把stdafx.h预编译头删掉,否则其它应用删不删都无所谓了。
但是……但是……但是……即使我采取了以上办法,并一一追踪我自己写的头文件,看了看winsock.h和winsock2.h包含的先后关系,都满足了winsock2.h在前的关系了,但是仍然有重定义,这个时候我看到另外一篇文章,里面提到【但当我在一个wxWidgets中调用它时,又出现那个让人厌烦的错误 ““sockaddr”: “struct”类型重定义,明显是wxWidgets先包含了windows.h,现在头都大了,楞想不到怎么解决,在所有文件最开头定义_WINSOCK2API_都没用】,只想说呵呵了。人家要是愣是在最初给你先包含了windows.h文件(就譬如MFC中的stdafx.h头文件),那你也没辙了是吧。
终极办法:
然而,天无绝人之路,终极办法是:添加WIN32_LEAN_AND_MEAN宏定义,直接在vs的设置里预先添加这个宏定义就ok啦:
那么,这个奇怪的宏定义是干嘛的,查了一些资料后,是这么说的【 不加载MFC所需的模块。在编译链接时,以及在最后生成的一些供调试用的模块时,速度更快,容量更小。】好多地方都是这么说的,就不给链接了,有兴趣的自己搜搜这个宏吧。
然而,我仍然疑惑的是,我在哪里加载MFC所需的模块了,其实我挺好奇上面那个图中_WINDOWS这个宏是干嘛,但是暂时没有搜到相关资料。
总结:其实大家也看到了,其实所谓的终极办法也只能解决这种非MFC的应用程序的问题,至于其他情况出现这种问题的话,我还没有去探索,毕竟还没有遇到嘛。
感慨:下面这些选项在不了解情况的时候不要瞎选哈:
还有那个SDL检查,个人建议不要选,因为windows上有它自己的一套_s的安全函数,否则,你就各种编译不通过,还得改为它的_s(safe)函数,这个时候你要修改的东西多了。当然,这个sdl检查还是有用的,毕竟人家的函数毕竟比较safe嘛,然而上次使用vsnprinf_s函数的时候,因为它提供额外参数问题,这个参数的错误导致我的程序里出现了莫名其妙的错误,都是泪。
要不是因为被要求使用vs做开发,我也不会去用它,个人还是钟情于linux平台的东西。vs开发为了让开发更简单,更傻瓜式,它默默的帮你干了很多事情,等你出错的时候,你就干瞪眼吧。也因为各种IDE的使用,很多程序员不了解整个编译流程,总是习惯一键build。当然,各有各的好,各有各的适用情况,我个人偏好使用gcc罢了。