作者:孟岩 来源:CSDN博客 酷勤网收集 2007-12-09
Danny Kalev是Informit.com网站C++板块的主持人,一个我比较欣赏的、死忠于C++的、略带有神经质的、敏感的blogger。今天他在informit上发表了一篇文章,题目吓死人:“Visual C++ 8.0劫持C++标准”。我赶忙跑来一看,原来是关于一个编译警告的。大致是这样的:VC++ 8.0对于std::copy算法的某种用法给出了这样的警告“此函数已经被废弃”。这还了得,惹恼了一向心地纯洁的Danny,于是写出文章来声讨。据他在文章里说,这个事情目前正在C++标准委员会的maillist中爆吵。
我觉得,C++有幸拥有一批像Danny Kalev这样的纯洁主义者,才没有成为巨人手中的玩物。C++也有幸拥有一些像Microsoft这样的big player,才能不断搞些新花样出来,不至于窒息而死。微软为什么要对这个std::copy提警告,原因很简单:安全性。这个std::copy的行为跟C语言的strcpy, memcpy差不多,是不由分说的,不计后果的。只要你脑子短路一秒钟,这个算法就能让你的应用程序分崩离析。
我该支持VC++的做法吗?也支持也不支持。正如我准备在马上召开的C++技术大会上的演讲里说的那样,一切有助于提高C++生产率的改进都是值得赞赏的。如果VC Compiler只是温存的建议和善意的提示一下,那么我想这里是没有任何争议的。这个提示也许可以让你避免几个星期的痛苦的debugging,对于生产率的提升效果不言而喻。然而,微软的警告用语是蛮横的,越过了界限。“废弃?”,微软认为自己有权废弃一个ISO标准中的算法?仅仅因为自己开发了一个编译器?这就好像是说,一家生产皮尺的公司可以改变1米的度量一样可笑。Danny通篇抨击的也就是这一点。
不过问题在于,看看这个标题,“劫持”,Danny,你的用语是不是也越过了界限呢?不管怎么说,我不认为VC8与标准C++是对立的东西。不,我认为VC8不是邪恶势力企图将C++引入歧途的工具,而是引导C++迈向未来的重要一步。只不过,微软即使要裹挟C++,动作也应该温柔一点。毕竟这不是你自家的VB和C#,想怎么掰持就怎么掰持。
评论
analyst 发表于2005-11-16 18:13:00 IP: 218.242.140.*| 呵呵,有点神经过敏了。其实对于实用主义者来说,这种警告非常人性化。 |
master 发表于2005-11-16 18:16:00 IP: 10.40.51.137, 211.96.102.*| 废弃就是,有了更好的替代品,或者替代的方法, 你应该问,废弃了这个,那我该用什么,人家MS早都给你想好了 |
周星星 发表于2005-11-16 13:24:00 IP: 221.6.3.*| 我认为VC8不是邪恶势力企图将C++引入歧途的工具 --- 我认为不是 ,而是引导C++迈向未来的重要一步 --- 我认为更不是 |
wozhaolaal 发表于2005-11-16 20:48:00 IP: 61.147.154.*| vc8是不是.net 2005里面的??? |
utstar 发表于2005-11-16 20:54:00 IP: 10.50.37.55, 211.96.102.*| 据说MS已经改正了这个做法,可为什么我在vc2005 express里面还是看到这个警告? |
utstar 发表于2005-11-16 20:59:00 IP: 10.50.37.55, 211.96.102.*| 才注意到这篇文章作者原来是梦魇,好像还是个名人吧?你怎么能伙同MS一起绑架c++标准呢?评论的后半部分就是在误导读者 |
billjoy 发表于2005-11-16 14:18:00 IP: 219.144.130.*| 星星老大的看法我支持! |
panic 发表于2005-11-16 22:03:00 IP: 218.85.96.*| 微软对template的误解还是很深的嘛~ stl本来就是希望用被作用类型最恰当的方式操作他们,你拷贝pod类型,难道不希望像memcpy一样快捷干脆么? |
bigstupidcat 发表于2005-11-16 22:07:00 IP: 211.161.23.*| 你去看看嵌入式系统的代码,strcpy,memcpy,memset等东西都是满天飞的,怎么叫不安全?凡事没有绝对。。。。。 |
bigstupidcat 发表于2005-11-16 22:08:00 IP: 211.161.23.*| 你去看看嵌入式系统的代码,strcpy,memcpy,memset等东西都是满天飞的,怎么叫不安全?凡事没有绝对。。。。。 |
ljh 发表于2005-11-16 01:28:00 IP: 219.133.124.*| > ...跟C语言的strcpy, memcpy差不多,是不由分说的,不计后果的。 您认为一个行为良好的strcpy, memcpy应该设计成怎样呢? 难道一向安全,高效,和善的C语言也变得这样扑朔迷离了? |
Buzzard 发表于2005-11-16 22:50:00 IP: 61.141.252.*| strcpy,memcpy,memset等东西在嵌入式代码里可以满天飞那是因为那部分代码没有和用户交互,或者说没有一个shell.如果敢在Unix/Linux也这么搞,很有可能造成问题.因此对于这样的不安全的函数,给出一个警告信息没什么不对.早都有strncpy这样的函数,为什么不用?安全编码要养成习惯. |
csdn越办越差了 发表于2005-11-16 22:54:00 IP: 218.18.139.*| “/”应用程序中的服务器错误。 超时时间已到。在从池中获取连接之前超时时间已过。出现这种情况可能是因为所有池连接都已被使用并已达到最大池大小。 说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.InvalidOperationException: 超时时间已到。在从池中获取连接之前超时时间已过。出现这种情况可能是因为所有池连接都已被使用并已达到最大池大小。 源错误: 执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。 堆栈跟踪: [InvalidOperationException: 超时时间已到。在从池中获取连接之前超时时间已过。出现这种情况可能是因为所有池连接都已被使用并已达到最大池大小。] System.Data.SqlClient.SqlConnectionPoolManager.GetPooledConnection(SqlConnectionString options, Boolean& isInTransaction) +396 System.Data.SqlClient.SqlConnection.Open() +384 template.DbObject.RunProcedure(String storedProcName, IDataParameter[] parameters) template.DataProvider.GetContent(Guid id, Boolean pageView) template.Business.GetContent(Guid id, Boolean pageView) template.display.Page_Load(Object sender, EventArgs e) System.Web.UI.Control.OnLoad(EventArgs e) +67 System.Web.UI.Control.LoadRecursive() +35 System.Web.UI.Page.ProcessRequestMain() +733 版本信息: Microsoft .NET Framework 版本:1.1.4322.2300; ASP.NET 版本:1.1.4322.2300 |
Viweei 发表于2005-11-17 01:58:00 IP: 220.165.201.*| 我也下载了VC8 。在不到一天的时间我就删了。不得不承认我确实没有完整的试用过。我还真是搞不明白是不是什么东西都要托管?都要net。是看到JAVA成功眼红了。还是C++以经没发展余地了,弄不到钱了?全都要搞到它的托管之下。更离谱的是,有些公司托管做什么还没搞清楚大招C#程序员。这是谁害的啊? 我只觉得既然要做一个程序员,有些事是你应该做的,在我第一次学习编程的时候。就知道作为程序员。内存和CPU 管理是我必须做好的。没有必要连这些也需要微软帮你做把?10内的开发语言。我想如果真是这样人人都改行玩net 了。10年后再也不会有人对微软说:“不”了。 |
army 发表于2005-11-16 16:27:00 IP: 202.109.12.*| 我也觉得《程序员》办的越来越差,上面很少有真正贴近程序员的文章,更多的只是对时髦技术的炒作。中国的软件业本来就很浮躁了,《程序员》反而起到了推波助澜的作用。《程序员》介绍的东西太杂,一会JAVA,一会.NET,一会WEB开发,没有专注于某个领域,博而不精,也导致了读者们不停的追赶时髦技术,却没有静下心来好好提高自己的编程功力。 |
新消息 发表于2005-11-16 16:38:00 IP: 218.2.214.*| “只要你脑子短路一秒钟,这个算法就能让你的应用程序分崩离析”--脑子短路一秒钟是我自己的事情,你微软凭什么废弃标准库的东西?什么叫相信程序员? |
hjl 发表于2005-11-16 09:39:00 IP: unknown, unknown, 211.100.22.*| C语言跟安全有什么关系?跟和善有什么关系? |
sevencat 发表于2005-11-17 09:14:00 IP: 219.136.207.*| 那帮C++委员会的人就是不思进取,看看跟JAVA相比,他们搞的有用的东东多吗? xml,regex,socket不知道什么时候才能进标准,估计进了也没人用了。 我FAINT。还吵来吵去。 我支持MS。不喜欢委员会的那帮学院派的爷们。 |
尊姓大名 发表于2005-11-16 17:26:00 IP: 218.246.97.*| "微软为什么要对这个std::copy提警告,原因很简单:安全性。这个std::copy的行为跟C语言的strcpy, memcpy差不多,是不由分说的,不计后果的。只要你脑子短路一秒钟,这个算法就能让你的应用程序分崩离析。" 哪位给介绍一下,怎么不安全了? 我的程序可是到处是 strcpy, memcpy :( |
Builder 发表于2005-11-16 17:38:00 IP: 219.128.172.*| 那MS该对所有用到指针的语句都警告要废弃才对。都给MS托管了就安全了。 |
非典型秃子 发表于2005-11-17 09:30:00 IP: 61.152.132.*| 为什么一定要进标准?boost+ace够不够你完成xml,regex,socket的任务? |
hyifeng 发表于2005-11-17 13:07:00 IP: 202.105.135.*| 周星星, 你说你这个例子能清楚地诠释“安全性”的真实含义, 就说明你没理解什么"安全性", 如果你真做过真正的系统,真正从事过开发,就明白什么是安全性, 就明白标准库的库和其他乱七八糟的第三方的库的区别. c++就是因为安全性, 和标准库太薄弱 导致生产稳定系统的难度远大于java, 导致生产力比不上java. 还有,如果你把c++ 和 java等其他语言的关系 理解成机床, 锤子/扳手/螺钉的, 就表示你认为c++也会象最经典的asm机床一样淡出, c++在努力地发展, 就是尽他所能, 适应时代的需求而不是死守一角. |
新消息 发表于2005-11-17 10:02:00 IP: 218.2.214.*| 还有李建中所说的,“C++/CLI实现了Bjarne Stroustrup 所说的可选的垃圾回收机制”。我想问,C++/CLI中的托管的垃圾回收机制真的是可选的吗?只要你用CLI,你就没办法做到可选,而是必须选择。 相比之下,我还是倾向于认为auto_ptr、boost::shared_ptr等智能指针更象是可选的垃圾回收机制。 C++里的东西很多,当然很多设计和C一样,性能放在首位。就像memset和std::copy,难道程序员不应该对它们的缓冲区负责吗?如果强行将这些安全认证加入,实际上就是犯了错误。 首先:性能问题,有一些场合我知道不肯能出现缓冲区问题,你却要都判断,实际上是个浪费。 第二:我们被告知在设计时应该始终注意关注点分离,即一个模块、一个类、一个方法都应该做一件事情,这叫职责内聚。 第三:依此类推,如果要实现线程安全怎么办,难道你在每一个方法里边都要加锁吗?显然。你的回答应该是“否”。那么凭什么这里要横加干涉呢? 依我看,这确实是微软在劫持标准,其实一个好的做法是,在上述类似的函数中加上断言,或者以另一种友好的口气告知,这个方法可能有内存泄漏问题,并简单告知处理方法。而不是粗鲁的“废弃”。 |
Ric 发表于2005-11-17 10:08:00 IP: 218.19.189.*| 其实我们讨论这个问题应该先从C++产生的基本立意来看。C++天生就不是强调安全性的(所以才出现了JAVA,C#),那是程序员的责任。C++的产生和最大的优势就是性能和灵活性。如果一味强调安全性来取代程序员的责任,这就违反了C++的哲学根本。这种演变是危险的,他将必然会对C++的灵活性和性能带来冲击,促使C++向java或c#演变。长此以往真正的C++将不复存在,世上只不过又多了一种所谓“安全”“简单”的语言。编程世界的多样性将遭到破坏。所以从鼓励多样性的角度看,我们应该保持C++的哲学根本立意,让它在自己的特殊道路上发展,给狂热程序员多些自由和责任。这样才能保证C++的魅力。 所以我认为只要给出温馨提示就可以了,不要干预程序员的行为。 |
zz3 发表于2005-11-16 11:35:00 IP: 220.250.6.*| 微软乱改c++语言又不是没有的事。如果没有c++标准委员会,微软不定就自己生产一个c++微软标准出来。 |
sevencat 发表于2005-11-17 13:48:00 IP: 219.136.207.*| ace中碰到BUG能把你给郁闷死。 假如库不重要的话,VC不会占这么大市场。bcc也不会这么快衰落吧。我不想从理论证明什么,我只想说这就是事实。 至于strcpy的安全性,我想不用多说了,那样用是自讨苦吃。 好多代码中的这种类型BUG,摆到人面前的时候都觉得很弱智,一般人不可能犯。这方面也一样,我只从事实说话,你说那样的是绝对安全的,但是你写个几千行代码下来,再修改个N行代码,我相信很多人都会出一些问题的,而这些安全的代码可以让你的代码出问题的可能性大大降低。 就拿最简单的空指针,学过C的都知道,为什么实际的BUG中还有很多是空指针造成的? |
sevencat 发表于2005-11-17 13:52:00 IP: 219.136.207.*| 还有,SOCKET没进标准,当然BOOST上面有人在开发(galileo),另外还有个asio.sf.net的也在开发,看看,加上ace和其他的一大批轮子。我不知道是不是有人觉得好玩。 xml也没进标准,所以我们不得不选用libxml2,expat,xerces,tinyxml,或者一些其他第三方的东东。 最常碰到的是在这个公司要用这个,那个公司要用那个,甚至同一家公司有的用这个,有的用那个。 regex就不说了,N个版本,似乎每个版本都有不少人在用。 标准的好处是不管在哪里,都是同样的代码。 |
短歌 发表于2005-11-17 14:02:00 IP: 192.168.123.177, 221.221.217.*| >>这个std::copy的行为跟C语言的strcpy, memcpy差不多,是不由分说的,不计后果的。 不知道这种说法从何而来,这个“差不多”的标准又是什么。std::copy将会调用被copy的每个对象的拷贝构造函数,strcpy和memcpy不会作这种事情,如果这也算是差不多的话,那么所有实现copy功能的代码是不是都应该算是差不多了?那我们还是不要copy算了。 有人说std::copy会越界,那应该是你传给std::copy的迭代子负责的事情,为什么要让std::copy来负起这个责任呢? |
dgod 发表于2005-11-17 22:11:00 IP: 221.137.148.*| 微软以安全为由,几乎对一切c标准库函数都提出警告,strcpy不安全倒也罢了,它连strncpy,fopen都提出警告,并提示用它的strcpy_s,那就恶心了,我实在看不出strncpy有什么需要 警告的,fopen呢,strcpy_s和strncpy好像没什么区别,只不过一个是标准的,一个是微软自家的而已 |
myan 发表于2005-11-17 14:17:00 IP: 219.236.53.*| to 短歌: >> 有人说std::copy会越界,那应该是你传给std::copy的迭代子负责的事情,为什么要让std::copy来负起这个责任呢? 你说的没错。不过你没有去看那个原文。如果你给std::copy的第三个参数是back_inserter,那么编译器不会报警。微软的考虑还是比较周全的。 to 周星星: 我说VC引导C++,另有意义。我认为C++应当也必须向不同规模和不同性质的平台分化,形成若干子标准,而不是人为维持一个大一统的标准,搞得好像裹脚老太太,举步维艰。在这个方面,VC目前的做法具有实质意义。 to sevencat & hyifeng: 知己难的 :-) |
马特拉伯 发表于2005-11-18 00:34:00 IP: 218.66.32.*| 一堆人在乱吵,真的很晕! 这就是C++的局面,C++比起Java和.NET,最大的特点就是乱!缺乏没有统一的库,缺乏统一的编码标准,缺乏统一的文档。 看看人家Java吧,经过十年的发展,已经和软件工程完美地融合在了一起。 生产力的发展,需要规模化,需要标准化,C++标准委员会成立这么多年,到底作出了多少成就?微软做出强大的库,是Win平台开发者的福音。 |
rh 发表于2005-11-17 11:41:00 IP: 219.141.37.*| @Builder "那MS该对所有用到指针的语句都警告要废弃才对。都给MS托管了就安全了。" ----大家都不要写程序了,程序全由MS来写,这样就最"安全"了... |
周星星 发表于2005-11-17 11:43:00 IP: 221.6.3.*| 这里高手就是多,俺也附庸风雅一回。 说VC引导C++那是不对的,虽然很多人用windows,虽然很多用windows的人使用VC,虽然VC++很强大,虽然windows上重要的应用软件很多是VC开发的,比如MS office,比如MS SQL Server,比如VS本身,…… 但VC引导了C++吗?哪个语法,哪个特性是由VC带入C++的?我也用windows,我也用VC,我也认为VC优秀,但VC只是比较完美的实现了C++,而不是“引导”,“引导”要有两个特征: a. 走在C++前面。(C++/CLI是走在C++前面?^_^,那是否定C++) b. C++跟随于其后。(也许很多人认为某些VC特性走在标准C++前面,但它们得到C++肯定并跟随其后吗?MFC,还是COM,还是managed C++,还是C++/CLI?只不过是一厢情愿罢了,不能代表C++群体的意愿) 而七猫同志说的就更不对了,xml,regex,socket应该去第三方库中去寻找,C/C++和Java/.net是有本质区别的,Java/.net是应用型语言,而C/C++是开发型语言,可以用C/C++开发出VB来做具体的应用,可以用C/C++开发出Java来做具体的应用,可以用C/C++开发xml,regex,socket等等来给Java/.net做具体的应用,当然也可以开发出xml,regex,socke来给自己做具体的应用,这也是可以的,尤其在新领域。 把C/C++比喻成一个机床,那么Java/.net/xml等等就是 锤子/扳手/螺钉,机床可以制造出锤子/扳手/螺钉,而七猫同志却希望机床本身要有锤子的功能(钉钉子)和扳手的功能(扳螺母)和螺钉的功能(绞合)。 关于“安全性”,诸位的意思我清楚,但描述得不是十分清楚,容易令不知道的人误解,我这么说大家看看可不可以: C++并不是不安全的,并不是不强调安全性的,对于“安全性”和别的某些语言的差别只在策略上,也就是说谁来保证什么程度的安全?别的某些语言全托付给编译器,而C/C++则不同意这种做法。我来举个例子: char buf[4]; strcpy( buf, "123" ); 请问strcpy哪里不安全了?这种做法何须警告? 对于 char buf[4]; strcpy( buf, variant/*一个长度可能超过buf容量的字符串*/ ); 这不是strcpy不安全,是你错误的用了strcpy,你应该用strncpy,C/C++保证安全,但不保证程序员无道理的瞎用。我曾经举了一个例子,使用自认为安全的Java编写如下语句: command( "死机" ); 如果运行这一句没死机,那么Java太烂了,竟然不按照程序员的意图执行; 如果运行这一句死机了,那么Java太烂了,程序运行时竟然会死机。 我觉得这个例子能清楚地诠释“安全性”的真实含义。 |
d 发表于2005-11-18 02:31:00 IP: 61.185.219.*| 如果MS真是善意要通过警告来提醒程序员安全问题,那么警告信息是不是应该这么写:std::copy is not completely safe, blah blah.或诸如此类的话?这和说std::copy被废弃(warning C4996: 'std::_Copy_opt' was declared deprecated)是不是有TMD天壤之别?MS,不是所有的程序员都象孟老大这般聪明,能从“std::copy被废弃”读出“std::copy不安全”你这样的“美意”的! 再说strcpy,memcpy,std::copy安全性问题,它们是有使用非法地址的隐患问题--这是事实,但这不是它们本身的问题。他们的使用是有严格条件的。违反操作规程的操作,都是可能“不由分说的,不计后果的。只要你脑子短路一秒钟,就能让你的应用程序分崩离析”。它们之所以有这样的隐患问题,是因为它们给了程序员更大的自由,更大的自由必然意味着更大的责任,这二者是不可分的。再说,C++标准库已经给了你很多可替代 直接内存复制/对象复制 的更“安全”的机制(会有轻微的执行效率损失,这是必负的代价),strcpy,memcpy,std::copy有没有拦着谁不能用这些东西?软件的安全性归根结底是要程序员负责任的,没有绝对安全的语言。语言在安全性上没有本质差别,只是对程序员的责任要求上有差别。不能把这个责任推卸给这些标准函数。这就好象有些人便秘--这是事实,但这不是地球吸引力不够引起的一样。 对yu MS引导C++,我觉得孟老大有点一厢情愿了。看历史就知道这是好是坏了:Basic =〉VB.net?Java =〉Javascript?C++ =〉C++/CLI?Visual Fortran =〉...(没了,被卖了)?别扯了。要真顺从MS的所谓引导,C++早不是今天的C++了,是VC6那个破烂倒很有可能。历史告诉我们正确的途径正好相反,不是MS引导了C++(感谢上帝),而是C++引导了MS。正是C++ ISO标准,才有今天C++元编程范式的辉煌(这是7年前谁都没有想到的),才迫使MS在VC开发上投入人力财力,才有今天的VC8。 |
发表评论 发表于2005-11-17 12:31:00 IP: 218.79.85.*| 星哥说的太精辟了, 学习之 |
阿土 发表于2005-11-17 16:43:00 IP: 222.65.96.*| 不懂 反正觉得《程序员》很花的 很多东西看不懂。 感觉很多东西很浮夸的。 很多时候 好像在钻研 一种一劳永逸的方法。一种可以大规模提高生产力的东西 。 写程序 靠的是人。 1w个我加在一起也写不出linux内核 |
x 发表于2005-11-17 12:41:00 IP: 218.4.73.*| 如果说一个学武术的人不会用刀,而伤自己的话,只能说你学艺不精,而不是刀的问题。 如果每次刀砍人之前先检查一下是否是用刀者自己,或者用刀者的亲戚朋友,验证一下是否安全,大概这位老兄早被别人砍死了。 微软造的这把刀有这个功能,不过要选择clr的刀,但是这把刀不能代表武林中所有的刀吧? |
新消息 发表于2005-11-17 16:51:00 IP: 218.2.214.*| 看了myan老大的发言以后,我去查了一下std::back_inserter,发现其定义如下(VC 7.1): template<class _Container> inline back_insert_iterator<_Container> back_inserter(_Container& _Cont) { // return a back_insert_iterator return (std::back_insert_iterator<_Container>(_Cont)); } 而back_insert_iterator是如下定义的: template<class _Container> class back_insert_iterator : public _Outit { // wrap pushes to back of container as output iterator public: typedef _Container container_type; typedef typename _Container::reference reference; explicit back_insert_iterator(_Container& _Cont) : container(&_Cont) { // construct with container } back_insert_iterator<_Container>& operator=( typename _Container::const_reference _Val) { // push value into container container->push_back(_Val); return (*this); } back_insert_iterator<_Container>& operator*() { // pretend to return designated value return (*this); } back_insert_iterator<_Container>& operator++() { // pretend to preincrement return (*this); } back_insert_iterator<_Container> operator++(int) { // pretend to postincrement return (*this); } protected: _Container *container; // pointer to container }; 而copy则是这样定义的: template<class _InIt, < |
bluemiles 发表于2005-11-17 16:53:00 IP: 220.249.19.*| 我还是觉得, 恩, 代码安全性是程序员素质问题... 没有理由指责某函数不安全, 因为使用它们是程序员的决定, 训练有素的程序员能应对各种情况~ |
周星星 发表于2005-11-18 10:31:00 IP: 221.6.3.*| to 7cat: “不管什么语言最终总会灭亡,环境总会在变化,要追求不变的东东,你觉得有价值吗?你说的这种永远没有不持久的语言也存在,我们一般叫他"汇编",但他在实际项目中用得是越来越少了。” ------ 也许你这种观点是没错的,但你既然有如此需求,那你就应向VB中去寻找,VB向来有什么就加什么,而不是去抱怨C/C++,因为C/C++并不认同这种观点。而且Bjarne Stroustrup说过,C++是通用语言,你应该裁剪并扩充成适合你工作需要的集,如果你真觉得strcpy是个祸害,觉得“XML在项目中用得多”的话,你就应该裁剪C++为“C++ without strcpy and with XML”,并在这个"XML用得多"的社区中需求标准化。这样各得其所,你有了标准化的XML库,同时C++也不会为XML所拖累。 其实追求变还是不变只是在一个程度上有所不同而已,并没有本质的对立。你是聪明人,无须多说。另外你觉得是什么使得C++拒绝这些易变的东西?当然是整个C++用户群,而不是某个个人。 另外,你说的“警告多完全是好事”我也不赞同,其一,那种做法是符合C++标准的,那就不应该去警告,简单的说就是“既然是正确的,那又吠个啥?”。这又要通过两个方面来阐述了: a: 谁来定义她应当安静通过还是给个警告?答案当然是C++标准,因为这是标准C++的内容,不是M$的,M$把它自己的WritePrivateProfile说成是Obsolete的,那是它的权利,虽然看起来有些滑稽。 b: M$有没有权利在自己的VS中对C++胡说八道?答案当然也是否定的,嘴虽然长在自己身上,但公开场合说话还是要守法守道德的。 其二,警告多真的是好事?在strcpy上出问题的毕竟少,在程序逻辑上出问题的肯定多,那么霸道的M$是不是也应该在你的每条语句上给出一个警告?告诉你“你的这条语句是不安全的,被荒废的,请联系M$的工作人员来给你编程”。 |
tt 发表于2005-11-17 17:00:00 IP: 218.17.5.*| xml 这种垃圾也想进标准? |
周星星 发表于2005-11-17 18:18:00 IP: 221.6.3.*| 如果我用strcpy的话,VS2005就会跟我说: warning C4996: 'scanf' was declared deprecated. 看来这个警告力度中等,虽然会令别人感觉不快,但不至于暴跳如雷。当然,我觉得应该更克观点说,说成:“你的用法是正确的,但M$善意的提醒你需要您自己保证代码的安全性。”,而且这个警告不应该是默认的,应该在使用某种苛刻的检查设置时才应该跳出来秀一下,因为它虽然善意,但也令人觉得霸道。 “tt:xml 这种垃圾也想进标准?” --- 严重支持! |
挨踢吟 发表于2005-11-17 18:33:00 IP: 222.240.184.*| 強烈反對 標準就是標準 豈容M$亂改 C\C++就是要效率第一 不然不要用好了 |
to 7cat: 发表于2005-11-17 18:34:00 IP: 221.6.3.*| 请鬼容易送鬼难! 把那些东西加进C++标准很容易,但等它们过几天后不再时髦时怎么办? 作为一个通用的语言应该关注持久的技术,而不是时髦的技术。要想时髦完全可以由第三方提供嘛。 |
yangyang 发表于2005-11-17 18:56:00 IP: 222.68.249.*| ms 喜欢在编译器里写什么样的警告,那是ms 自己的事... 不喜欢大不了不用, 说到底都是d 版宠坏了... 如果要半年工资买一个IDE,保证喜欢的不得了...BS... |
jecky 发表于2005-11-17 19:10:00 IP: 61.144.193.*| 我不以为然, C++在进步是件好事情, 这个警告缘于MS改进了一套C标准库,然而C++的底层实现调用了C标准库函数,警告由此而来.C标准库的改进我个人觉得太必要了,但不知权威的ISO为什么还不作修订 |
sevencat 发表于2005-11-17 20:23:00 IP: 219.136.207.*| tt 发表于2005-11-17 5:00 PM IP: 218.17.5.* xml 这种垃圾也想进标准? //================================= 对XML本身我不评论,请你仔细问问其他人XML在项目中用得多不多。 to 7cat: 发表于2005-11-17 6:34 PM IP: 221.6.3.* 请鬼容易送鬼难! 把那些东西加进C++标准很容易,但等它们过几天后不再时髦时怎么办? 作为一个通用的语言应该关注持久的技术,而不是时髦的技术。要想时髦完全可以由第三方提供嘛。 //=============================== 不管什么语言最终总会灭亡,环境总会在变化,要追求不变的东东,你觉得有价值吗?你说的这种永远没有不持久的语言也存在,我们一般叫他"汇编",但他在实际项目中用得是越来越少了。 BTW:个人觉得警告多完全是好事。好多人不是喜欢把警告调到最高级别吗?做到编译过来一个警告也没有,就很厉害了,起码出错的可能性要小多了。 glibc2.35对这方面也有不少的扩展,好像很少看到有人说东道西的。 |
goodman 发表于2005-11-18 15:45:00 IP: 218.66.48.*| good |
lsk 发表于2005-11-19 00:09:00 IP: 210.21.76.*| 怎么这个语句用不了 int a=24; cout<<a<<endl; |
aska 发表于2005-11-18 16:18:00 IP: 218.25.42.*| 骂吧,大家把时间都浪费在骂战上,有趣是吧,不爱看拉到贝,唉!成天骂来骂去的,真累 |
abc 发表于2005-11-19 01:59:00 IP: 218.186.152.200, 202.156.6.*| 小屁孩,XML就不说了,SOCKET进标准bj老早就提倡了 --------------------------------------------- 不过是在个 wishlist上,搞的跟存在一样。知道什末叫wishlist吗? 谁大谁小就懒得说了,当年在csdn上还混了两个月,怎末就没见您这末牛的人物啊? |
Avlee 发表于2005-11-18 16:19:00 IP: 222.88.61.*| 我一直没有看懂xml怎么进标准,对什么进行标准化呢?来个std:xml?无非是对xml相关标准的一个实现,和std融合,难道比用xerces-c,libxml2,expat...好吗? |
abc 发表于2005-11-18 16:37:00 IP: 218.186.152.200, 210.193.52.*| 写这篇的是lj,这年头lj也发言,真是讽刺啊。 想安全,嘛都不做,回家睡觉去吧。java安全,有本事写个用mmx的程序出来啊? 至于什末xml,socket要进标准的bc们,还是用您的java,c#去吧,您喜欢跟着别人的规矩走,并不表示别人喜欢。 |
yangyang 发表于2005-11-18 16:39:00 IP: 222.68.249.*| "您尝试发送的文件经检测可能包含潜在的不安全因素,因此未被发送。" 完了, MSN 劫持 网页标准? .JS 文件被废弃了 MSN 劫持 Windows标准? .DLL .EXE文件被废弃了 ... MSN 劫持了大量标准 MS的东西就是喜欢劫持标准 MS是虐待狂 |
step_by_step 发表于2005-11-19 17:01:00 IP: 221.226.224.*| title吸引眼球,所以进来看看了~ 本来只是一个比较敏感的c++ fans写了篇文章,起了一个比较吸引眼球的标题,结果大家又如往常一样的吵起来了~有趣,大家继续吵~ |
sevencat 发表于2005-11-18 17:43:00 IP: 219.136.207.*| abc 发表于2005-11-18 4:37 PM IP: 218.186.152.200, 210.193.52.* 写这篇的是lj,这年头lj也发言,真是讽刺啊。 想安全,嘛都不做,回家睡觉去吧。java安全,有本事写个用mmx的程序出来啊? 至于什末xml,socket要进标准的bc们,还是用您的java,c#去吧,您喜欢跟着别人的规矩走,并不表示别人喜欢。 //============================ 小屁孩,XML就不说了,SOCKET进标准bj老早就提倡了。 |
neverbye 发表于2005-11-19 23:22:00 IP: 211.158.195.*| 印象中喜欢JAVA的人,一般更遵循标准,达成一致,循规蹈矩一些;喜欢C++的都是一些桀骜不逊,但更加有个性的人。 |
useresu 发表于2005-11-20 00:08:00 IP: 222.35.55.*| java,C++ 这个东西跟人群和思想还是有很多关系的, java的安全,C++的灵活, 如果能够把2者有机的融合,当然好, 即使不然,有向好的方向发展的欲望也是无可厚非的, 这中间就是有个尺寸的把握, 标准也不是一成不变得东西 btw: 我并不喜欢C++/CLI 也觉得ms还没有能够引导C++ |
TripleX 发表于2005-11-20 00:55:00 IP: 222.128.6.*| 关于安全性 我的理解是 不存在实际的内存越界访问 真的存在一个空指针其实并不危险 用gdb很容易追踪到 在java里也有空的引用 也很容易追踪到 安全上的漏洞来源于 写了不该写的内存但是没有引发一个系统错误 比如 int foo(char *s) { char buf[80]; sprintf(buf, "%s", s); ... } 一般的说如果s太长 那么指针会越界 产生一个段错误 这样并不危险 危险在于一个经心构造的s不会产生段错误 它会把foo的返回地址覆盖掉 如果把foo的返回地址指向 栈中的一段内存 而那段内存又是用户输入的话.....那么就 会产生一次缓冲区溢出 hacker可以获得shell 或者运行 什么别的东西 ok 现在我们来看std::copy std::copy不比较源和目的的大小 所以也可能把敏感的内存内容覆盖掉 而对于 std::back_inserter 用push_back替代了=操作符 所以是不会越界的 从这个角度说 sprintf缺少一个边界检查的功能 但是snprintf和memcpy都不缺少 它们都有一个size参数 能保证写入的东西不会越界 所以作者举例子说memcpy不 安全是不恰当的 其实从c的习惯来说 像sprintf这样的函数也不能说是不安全的 只能说缺乏边界检查 但是程序员毕竟可以自己做检查 只有gets()这样的函数才是真正不安全的 程序员根本没有办法 做边界检查...... 我喜欢memcpy 在很多编译器里是极度优化并且是在编译器上 实现inline的 根本不通过libc 忒鸡巴快 |
TripleX 发表于2005-11-20 01:38:00 IP: 222.128.6.*| 发现自己的re文还没说完 ft 再说回安全性 如果是以不存在实际的内存越界访问标准来衡量的话 那么不仅是gets()不满足 snprintf和memcpy也不满足 因为程序员 的错误也会导致越界访问 但是std::copy如果是用std::back_inserter的话 就没有问题 程序员顶多能造成一个段错误 但是无论如何也不可能利用它覆盖别的对象的内存 在.net和java 里 也完全不存在越界访问的问题 在内存被实际写之前 系统就会 抛出一个异常了 不象本地代码 一直写到没有页表项的地方才会 有段错误 所以我是这样把这些东西的安全性分级的 gets() < strcpy,sprintf,std:copy < memcpy, snprintf < std:copy with back_inserter,fprintf with memory stream,java,.NET... 对于程序员来说 也许只有gets()是被禁止的 strcpy和sprintf在有用户输入的地方 要小心的用 因为它们并不比 对应的安全性更高的snprintf strncpy快多少 所以一般还是建议用带n的版本 至于java .NET来说 安全性是比较高 基本没可能写出带缓冲区溢出 漏洞的代码(除非runtime或者native method有问题) 但是那个 已经不是本地代码了 和c/c++没有什么可比性 根据我的经验 像 snprintf这样的函数程序员的脑袋已经很照看得过来了 sprintf还是 要小心使用 memcpy依然是我最喜爱的 如果手头正好有一个变量 已经有字符串的长度 我喜欢用它代替strcpy |
xlsue 发表于2005-11-20 09:49:00 IP: 222.218.121.*| 自己刀子耍不好,就怪别人?伤了自己,就说刀子太锋利了?酒后开车出了车祸,就说别人造的车子不行?问题应该是当事人,你明明知道那是危险的,你干嘛不小心?如果你的技术不行,更应该小心翼翼。 iterator制定的时候就没考虑他安全性,为了效率。那安全性就交给程序员了。因为他们相信程序员。在C中,数组越界,出现野指针也是常有的事,要避免这些也是程序员的责任。C标准委员会也没有因此而改变C语言或废弃某个函数吧? |
zdgdh 发表于2005-11-18 22:30:00 IP: 61.187.121.*| 应该说VC++仅仅是Windows平台的家伙呀,我周围许多同志在用C++但主要是Unix平台,没有感觉到VC++会劫持什么。 |
Robbie Mosaic 发表于2005-11-18 12:46:00 IP: 211.167.159.*| 其实是可以把这些警告禁用的: cl /clr /D_CRT_SECURE_NO_DEPRECATE prog.cpp qsort.cpp 定义上面这个 _CRT_SECURE_NO_DEPRECATE 就可以把这些警告禁用了。 真的,这些警告是善意的,因为它们可以被取消。 但是,我从来都用 strcpy,照样可以做到安全,因为我每次调用它之前都检查字符串的长度是否足够。 strncpy 倒是不怎么用,因为它不保证建立字符串最后的那个 '\0'。 当然,微软的那些 secure 的函数也是不错的,不过由于不在标准库中的关系,我还是持观望态度,除非有人要求我使用它们。 |
登峰 发表于2005-11-20 11:53:00 IP: 202.107.216.*| Ric 发表于2005-11-17 10:08 AM IP: 218.19.189.* 其实我们讨论这个问题应该先从C++产生的基本立意来看。C++天生就不是强调安全性的(所以才出现了JAVA,C#),那是程序员的责任。C++的产生和最大的优势就是性能和灵活性。如果一味强调安全性来取代程序员的责任,这就违反了C++的哲学根本。这种演变是危险的,他将必然会对C++的灵活性和性能带来冲击,促使C++向java或c#演变。长此以往真正的C++将不复存在,世上只不过又多了一种所谓“安全”“简单”的语言。编程世界的多样性将遭到破坏。所以从鼓励多样性的角度看,我们应该保持C++的哲学根本立意,让它在自己的特殊道路上发展,给狂热程序员多些自由和责任。这样才能保证C++的魅力。 所以我认为只要给出温馨提示就可以了,不要干预程序员的行为。 --------------------------------- 这位仁兄的观点,已经说明了问题了本质 |
tseug 发表于2005-11-18 14:18:00 IP: 211.141.66.*| 我也是从试刊就支持程序员杂志的,后来尽管越来越差劲,里面充满了互相吹捧之辞,但我还期期购买,不过我早都不把它当做技术刊物了,程序员明明是娱乐刊物么! |
jemmy 发表于2005-11-21 17:14:00 IP: 207.46.89.*| 不就是个警告吗....... 搞的这么大动静干什么, MS又没有真的让它obsolete. 那个删了VC8的谁, 你不会是以为VC8就是用来写C++/CLI程序的吧? |
ksl 发表于2005-11-18 15:03:00 IP: 222.76.250.*| to **:咱俩的观点还是比较相似地 |
造极 发表于2005-11-20 23:15:00 IP: 221.226.215.*| 然也 |
还不是程序员 发表于2005-11-21 13:43:00 IP: 59.61.103.*| vc是一个商品,不喜欢就不要购买,不要使用,jjyy干嘛? |
一笑 发表于2005-11-27 23:06:00 IP: 58.34.61.*| Buzzard 发表于2005-11-16 10:50 PM IP: 61.141.252.* strcpy,memcpy,memset等东西在嵌入式代码里可以满天飞那是因为那部分代码没有和用户交互,或者说没有一个shell.如果敢在Unix/Linux也这么搞,很有可能造成问题.因此对于这样的不安全的函数,给出一个警告信息没什么不对.早都有strncpy这样的函数,为什么不用?安全编码要养成习惯. >>> 常见strcpy而不常见strncpy的原因其实很简单:strcpy通用而strncpy不通用。我甚至会自己写一个my_strncpy也不用库里面的strncpy。C代码在嵌入式代码里面满天飞我觉得已经很值得庆幸了,你还没见汇编代码满天飞,那才叫可怜呢。有时候效率还真是重要,有时候一个产品仅仅一处的效率不合格就是一个失败的产品——卖不掉,或者没人买。语言是人造出来的,人就应该有能力去改造;像java这种限制思维的东东,就注定它只能做为半自动化的生产线,要想用java来写个jvm,我估计我有生之年是看不到了。:) |
一笑 发表于2005-11-27 23:15:00 IP: 58.34.61.*| sevencat 发表于2005-11-17 1:48 PM IP: 219.136.207.* ... ... 至于strcpy的安全性,我想不用多说了,那样用是自讨苦吃。 ... ... 就拿最简单的空指针,学过C的都知道,为什么实际的BUG中还有很多是空指针造成的? ----------- >>> 嘿,好久不见猫兄了,原来在这里打嘴仗。:)还真把我的兴致给挑起来了:我就一个问题,既然C那么容易出bug,为什么还有那么多领域非C不可?原因只有一个,万物存在皆有理由。C从诞生到现在也有近30年了吧?我真想不出C#能不能比他活的时间长。(别急,别急,偶是M$盲,让偶掰着手指头想想MFC、DAO、ADO、OLE这些M$一手创造的名词儿都活了几年啊?! ^_^) |
ljh 发表于2005-11-28 10:12:00 IP: 210.21.221.*| Danny Kalev曾是C++标准委员会成员,这里一圈子人,恐怕都望不到其项背。 |
sevencat 发表于2005-11-28 19:09:00 IP: 219.136.207.*| 我就一个问题,既然C那么容易出bug,为什么还有那么多领域非C不可?原因只有一个,万物存在皆有理由。C从诞生到现在也有近30年了吧?我真想不出C#能不能比他活的时间长。(别急,别急,偶是M$盲,让偶掰着手指头想想MFC、DAO、ADO、OLE这些M$一手创造的名词儿都活了几年啊?! ^_^) //=================== 时间长短跟一个语言的用处不太能相提并论。 活的时间长不代表一切。 在很多领域中C语言已经被取代,而以前C语言基本是一切。 |
一笑 发表于2005-11-28 22:30:00 IP: 58.34.61.*| to sevencat : 嘿!少灌迷魂汤!:p |
没意思的争吵——我也够无聊了 发表于2005-12-06 22:44:00 IP: 221.200.60.*| 总结下: 1、说strcpy、memcpy有问题,主要是关于BOV(缓冲区溢出)的,这种错误,我想90%的程序员都会犯,从这个角度上说fopen确实会有问题......,这个问题从C++ fans的角度,那是希望大家都不要用char []就行了,但从OS厂商来说,提供API全部是string而非char*/char[]是不可能的,原因就在于C++自己没有统一的ABI接口。所以这是C++无法解决的一个大毛病。 2、说std::copy有安全问题,myan的表述不算大错。前面也有人指出了,因为std::copy使用=oprator,实际上还是不能避免BOV,比较而言,back_inserter会好一些。不明白的去找些关于缓冲区溢出的代码试试就知道了。 3、MS的提示不厚道,我想应该是某个程序员的无心之作,并不能代表MS的官方想法。 |
somebody 发表于2005-12-22 23:33:00 IP: 221.232.8.*| 微软这个警告不合理。 C++本来设计得就是让程序员负最终责任的,STL里面很多可能访问越界的地方,微软是不是都要来个警告?那干脆把STL废了算了。 |
无锋之刃 发表于2006-01-12 17:25:00 IP: 220.249.30.*| 呃,想不到一条出错信息居然引出这么多饼子堂的家伙斗嘴,真是蝴蝶效应的最好诠释。 安全性并不是绝对的,如果足够小心,C/C++代码的安全性不比Java之类的“完全统一”语言编写的代码差。只是有多少公司真正愿意把精力放在处理安全性上面? 使用一个工具,其目的是解决问题,而不是乱上添乱。做项目不比写程序,是有进度要求的。使用“由厂商一手包办的、足够安全”的语言来编写代码,再从硬件上提高执行效率的方案,比使用“足够快但不安全的”C/C++语言来解决这个工程要快多了--也就是说我们还要考虑开发效率,而不仅仅是执行效率本身。 一种技术体系不可能因为它不安全或者不够快,就因此消亡,而是会持续地存在很长时间。毕竟,更换技术体系的成本并不是哪个公司都能负担得起的。 过份纠缠于语言层面的东西,是不是把精力投错地方了?“拿到锤子就以为整个世界都是钉子”,这种做法不可取。 |
ccc 发表于2006-01-20 11:19:00 IP: 218.22.21.*| 我觉得微软确实太霸道了,竟然把ISO标准的东西废弃了,而用自家的东西替代。如果所有公司都这样,还要标准化组织干啥?微软这样的做法明显一点都不把ISO标准放在眼里,唾弃! 有人觉得没有必要纠缠于这种小问题,我只想说自由要靠自己争取。大家每次放弃一点点原则,总有一天大家发现自己成了微软的奴隶或被微软deprecated。 我建议大家都抵制这种东西,反正我是决不会使用这些_s的函数的,除非这些进入ISO标准,我不是傻子,知道什么时候该自己动手检查缓冲区。至于C++/CLI这个垃圾更是看都不会看。 |
ccc 发表于2006-01-20 11:28:00 IP: 218.22.21.*| 补充一点,C++/CLI完全脱离了C++的原则,与C++的哲学根本是背道而驰的。相信这种东西是微软创造的又一个短命鬼,微软自己扇自己耳光的例子太多了,它扇自己耳光不要紧,可苦了那些紧跟它的程序员。只要微软不改变其功利的本质,这样的事情还会不断出现。 |
sevencat 发表于2006-01-21 11:43:00 IP: 219.136.207.*| C++本身就已经在逐渐走向衰退,而java和C#在很快的发展之中(当然不要责问我说有XX项目或者XX项目除了用C++,用其他做不到,这些项目的总体的数量不是很多,而且这些项目的领域在越来越少,就说时间空间要求相当严格的大型应用,我想90%的C++程序员是基本没机会去做的) C++的库设计和语言设计的方向都不是向更易于使用发展的。 C++的语言被模板搞得支离破碎,更加涩难懂。C++委员在一些微言大义上大做文章。 C++的库设计并不是考虑到使用者的,很多是过度设计+过度优雅(最简单的例子,看string和其他的string的设计,这个string可能是比较优雅的,但基本上是最难用的),在某些角度上看,有很多甚至不如c库。 再看看BOOST,所谓的新一代的C++库,里面大多数的库一般项目根本用不到,而一般项目用得到的库他又不提供(对比JAVA和C#的库就知道了),他的代码也难以读懂,这样又会失去很多的用户,也难以使用。就拿上面的网络库来说,有人说有了ace了,为什么还要其他的什么网络库,好的,一个小组假如有12个人,这些库都要熟悉的话需要的时间周期太长,对人员的素质要求也极高。(很惭愧,我也很笨,boost的一些东东看来看去不懂,ace里的一些东东现在还是不会用) 我是实用主义者,说什么魅力,什么哲学,什么原则,我个人觉得都是很虚很空的东东,语言只是让我们来完成事情的,不是拿来吹嘘的,将C++这样形而上只会导致负面的结果。 BTW:我的C++功力可能很差,可能不如诸位,但我想中下水平还是有的。 |
ccc 发表于2006-01-21 22:58:00 IP: 218.22.21.*| 我承认java和c#都很不错,实际上我经常用c#做项目,但c++决没有走向衰退,他只是逐渐退出了一些他不擅长的领域,比如MIS系统,其实一种语言独霸天下本身就是不正常的。虽然大家平时最常见到的项目都是网络,数据库之类的,但最重要的程序绝大部分都是c/c++写的,比如各种系统软件,编译器,科学计算,嵌入式系统,各种大型桌面应用...太多了,大家只要看看自己你平时用得最多的程序就知道了,这些东西大家做得少,只说明一点,中国的软件水平太落后了,核心的东西都在别人手上,正因为如此,大家更不能放弃C++,中国程序员都不搞C++了,中国人就别永远别想做出重量级应用,生活在虚拟机或托管平台下的程序员就是将来的蓝领工人。 |
sevencat 发表于2006-01-22 12:52:00 IP: 219.136.207.*| 大家更不能放弃C++,中国程序员都不搞C++了,中国人就别永远别想做出重量级应用,生活在虚拟机或托管平台下的程序员就是将来的蓝领工人。 //============================= 大多数人根本无法选择,能做到自己选择的只有坐在研究所和大学院校的人,大部分人只有跟着市场走。研究那些核心的东东,大公司能承受,但中小型公司已经很难承受了。 |
李颖聪 发表于2006-02-22 00:32:00 IP: 61.140.135.*| 大家好,我觉得C++并没有没落,只不过对编写代码的人要求更高,在下用过很多语言,也使用过很多开发工具,总结后觉得C++写程序在一些细致操作上更加灵活,而JAVA的软肋是很明显的,你看SUN最新开发的JSF Studio就知道了,可能用了太多虚拟机的东西,速度慢到超离谱。至于C#,我觉得是个新秀,但有一些程序它也明显不适用,如网络多媒体传输,系统级的硬件访问等操作。每个语言都有自己的特点,只要你用好就OK。 至于说MS编译时发一些警告,这是很正常的,就算你是一个极高手的C++程序员,内存溢出也不可能杜绝,MS的出发点是好的,不过至于丢弃一些标准函数,这就不太好了,因为很多先前写的项目可能会用到。 |
tonny1982 发表于2006-08-07 23:55:00 IP: 61.135.146.*| strcpy, memcpy是不安全,前提是没有很好的使用它 那么你就用strncpy,但是在效率优先的系统中你可以忍受strncpy吗? 有空你可以测试一下strncpy |

