Browsed by
标签: Java

C++的坑真的多吗?

C++的坑真的多吗?

先说明一下,我不希望本文变成语言争论贴。希望下面的文章能让我们客观理性地了解C++这个语言。(另,我觉得技术争论不要停留在非黑即白的二元价值观上,这样争论无非就是比谁的嗓门大,比哪一方的观点强,毫无价值。我们应该多看看技术是怎么演进的,怎么取舍的。)

事由

周五的时候,我在我的微博上发了一个贴说了一下一个网友给我发来的C++程序的规范和内存管理写的不是很好(后来我删除了,因为当事人要求),我并非批判,只是想说明其实程序员是需要一些“疫苗”的,并以此想开一个“程序员疫苗的网站”,结果,@简悦云风同学 直接回复到 :“ 不要用 C++ 直接用 C , 就没那么多坑了。 ”就把这个事带入了语言之争。

我又 发了一条微博

@左耳朵耗子 新浪个人认证 说C++比C的坑更多的人我可以理解,但理性地思考一下。C语言的坑也不少啊,如果说C语言有90个坑,那么C++就是100个坑(另, 我看很多人都把C语言上的坑也归到了C++上来 ),但是C++你得到的东西更多,封装,多态,继承扩展,泛型编程,智能指针,……,你得到了500%东西,但却只多了10%的坑,多值啊

结果引来了更多的回复(只节选了一些言论):

  • @淘宝褚霸 也在微博里说 :“ 自从5年前果断扔掉C++,改用了ansi c后,我的生活质量大大提升,没有各种坑坑我。
  • @Laruence 在其微博里 说: “ 我确实用不到, C语言灵活运用struct, 可以很好的满足这些需求.//@左耳朵耗子: 封装,继承,多态,模板,智能指针,这也用不到?这也学院派?//@Laruence: 问题是, 这些东西我都用不到… C语言是工程师搞的, C++是学院派搞的

那么,C++的坑真的多么?我还请大家理性地思考一下

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 51 人打了分,平均分: 4.41 )
Loading...
Hash Collision DoS 问题

Hash Collision DoS 问题

最近,除了国内明文密码的安全事件,还有一个事是比较大的,那就是 Hash Collision DoS (Hash碰撞的拒绝式服务攻击),有恶意的人会通过这个安全弱点会让你的服务器运行巨慢无比。 这个安全弱点利用了各语言的Hash算法的“非随机性”可以制造出N多的value不一样,但是key一样数据,然后让你的Hash表成为一张单向链表,而导致你的整个网站或是程序的运行性能以级数下降(可以很轻松的让你的CPU升到100%) 。目前,这个问题出现于 Java , JRuby , PHP , Python , Rubinius , Ruby 这些语言中,主要:

注意,Perl没有这个问题,因为Perl在N年前就fix了这个问题了。关于这个列表的更新,请参看 oCERT的2011-003报告 ,比较坑爹的是,这个问题早在2003 年就在论文《 通过算法复杂性进行拒绝式服务攻击 》中被报告了,但是好像没有引起注意,尤其是Java。

弱点攻击解释

你可以会觉得这个问题没有什么大不了的,因为黑客是看不到hash算法的,如果你这么认为,那么你就错了,这说明对Web编程的了解还不足够底层。

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 32 人打了分,平均分: 3.94 )
Loading...
Resin服务器getResource揭秘

Resin服务器getResource揭秘

感谢网友 liuxiaori 继续分享其经历 )这样的详细的图文并茂的文章让我很佩服!

前言

接上文“ 由一个问题到Resin ClassLoader的学习 ”,本文将以this.getClass().getResource(“/”).getPath()和this.getClass().getResourceAsStream(“/a.txt”)为例,一步步解析加载的过程。

调试环境

  1. 下载resin3.0.23的源码( http://www.caucho.com/download/resin-3.0.23-src.zip )。
  2. 部署到myeclipse中,有错误,本人忽略了。Resin可运行。
  3. 将EhCacheTestAnnotation部署到resin3.0.23中。
  4. 调试this.getClass().getResource(“/”).getPath()。

问题来了,无论如何也模拟不出来<compiling-loader>所造成的影响,一直输出:/D:/work_other/project/resin-3.0.23/bin/ 。无奈之下,采用了这种方式:使用两个eclipse,一个使用发布版本的,部署EhCacheTestAnnotation进行调试;另外一个部署resin3.0.23源码,调试到哪里对照看源码。

开始

1) this.getClass().getResource(“/”).getPath()

本次调试涉及的所有类加载器为:

EnvironmentClassLoader$24156236[web-app:http://localhost:8787/EhCacheTestAnnotation]

EnvironmentClassLoader$7806641[host:http://localhost:8787]

EnvironmentClassLoader$22459270[servlet-server:]

[email protected]

[email protected]

首先进入Class的getResource(String name)方法,如下图:

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 13 人打了分,平均分: 3.46 )
Loading...
由一个问题到 Resin ClassLoader 的学习

由一个问题到 Resin ClassLoader 的学习

感谢网友 liuxiaori 分享其经历

背景

某日临近下班,一个同事欲取任何类中获取项目绝对路径,不通过Request方式获取,可是始终获取不到预想的路径。于是晚上回家google了一下,误以为是System.getProperty(“java.class.path”)-未实际进行测试,早上来和同事沟通,提出了使用这个内置方法,结果人家早已验证过,该方法是打印出CLASSPATH环境变量的值。

于是乎,继续google,找到了Class的getResource与getResourceAsStream两个方法。这两个方法会委托给ClassLoader对应的同名方法。以为这样就可以搞定(实际上确实可以搞定),但验证过程中却发生了奇怪的事情。

软件环境:Windows XP、Resin 3、Tomcat6.0、Myeclipse、JDK1.5

发展

我的验证思路是这样的:

  1. 定义一个Servlet,然后在该Servlet中调用Path类的getPath方法,getPath方法返回工程classpath的绝对路径,显示在jsp中。
  2. 另外在Path类中,通过Class的getResourceAsStream读取当前工程classpath路径中的a.txt文件,写入到getResource路径下的b.txt。

由于时间匆忙,代码没有好好去组织。大致能看出上述两个功能,很简单不做解释。

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 21 人打了分,平均分: 3.43 )
Loading...
API设计:用流畅接口构造内部DSL

API设计:用流畅接口构造内部DSL

感谢 @weidagang (Todd)向酷壳投递本文。

程序设计语言的抽象机制包含了两个最基本的方面:一是语言关注的基本元素/语义;另一个是从基本元素/语义到复合元素/语义的构造规则。在C、C++、Java、C#、Python等通用语言中,语言的基本元素/语义往往离问题域较远,通过API库的形式进行层层抽象是降低问题难度最常用的方法。比如,在C语言中最常见的方式是提供函数库来封装复杂逻辑,方便外部调用。

不过普通的API设计方法存在一种天然的陷阱,那就是不管怎样封装,大过程虽然比小过程抽象层次更高,但本质上还是过程,受到过程语义的制约。也就是说,通过基本元素/语义构造更高级抽象元素/语义的时候,语言的构造规则很大程度上限制了抽象的维度,我们很难跳出这个维度去,甚至可能根本意识不到这个限制。而SQL、HTML、CSS、make等DSL(领域特定语言)的抽象维度是为特定领域量身定做的,从这些抽象角度看问题往往最为简单,所以DSL在解决其特定领域的问题时比通用程序设计语言更加方便。通常,SQL等非通用语言被称为外部DSL(External DSL);在通用语言中,我们其实也可以在一定程度上突破语言构造规则的抽象维度限制,定义内部DSL(Internal DSL)。

本文将介绍一种被称为流畅接口(Fluent Interface)的内部DSL设计方法。Wikipedia上 Fluent Interface 的定义是:

A fluent interface (as first coined by Eric Evans and Martin Fowler) is an implementation of an object oriented API that aims to provide for more readable code. A fluent interface is normally implemented by using method chaining to relay the instruction context of a subsequent call (but a fluent interface entails more than just method chaining).

下面将分4个部分来逐步说明流畅接口在构造内部DSL中的典型应用。

1. 基本语义抽象

如果要输出0..4这5个数,我们一般会首先想到类似这样的代码:

//Java
for (int i = 0; i < 5; ++i) {
    system.out.println(i);
}

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 19 人打了分,平均分: 2.74 )
Loading...
那些曾伴我走过编程之路的软件

那些曾伴我走过编程之路的软件

收家的时候发现了一张VC++6.0的光盘,实然引发了我的怀旧情结。于是在 微博上感叹了一下 ,看到一些朋友的回应,还有朋友提到了Turbo C 2.0,于是更回放大了我的怀旧情绪,让我回想了很多N年前伴我走过编程之路的软件。现在看下来,有些感叹,又有些可笑。感叹的是技术发展的变迁,可笑的是当时的一些想法。(Unix/Linux是在大四和毕业的时候接触的,虽然这是我的强项,但是这下面的编程这么多年来没什么变化,所以就不提了) 注:图片较多,请稍等。

还记得第一次接触编程是在高中的时候,用中华学习机学Basic程序,后来到了大学,虽然学校的课程没有教Basic语言,但是DOS下有一个叫Quick Baisc的东西让我把高中时的知识又捡了回了。

大学里学的第一门语言是Pascal,所以,用的编程软件也就是Turbo Pascal,还记编译起来巨快无比,尤其是那个只有软盘和640K的基本内存的时代。

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 34 人打了分,平均分: 4.53 )
Loading...
你确信你了解时间吗?

你确信你了解时间吗?

你还记得“ 软件真的好难做 ”中的那个有意思的例子吗?那个例子告诉我们软件开发中假设可能会是致命的事。今天,我又在StackOverflow上看到一个关于时间的问题—— 为什么1927年12月31日的午夜时间这么奇怪 ?提问题的这个人给了下面的一段java代码(我做一些修改,保证让你可以copy过去就可以编译运行)

我在其中高亮了几行,这个程序就是想比较一下“ 1927-12-31 23:54:07 ”  和  “ 1927-12-31 23:54:08 ” 差几秒,很明显,是差一秒。但是程序的输出却不是这样的。

import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;
class time{
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        String str3 = "1927-12-31 23:54:07";
        String str4 = "1927-12-31 23:54:08";
        Date sDt3 = sf.parse(str3);
        Date sDt4 = sf.parse(str4);
        long ld3 = sDt3.getTime() /1000;
        long ld4 = sDt4.getTime() /1000;
        System.out.println(ld3);
        System.out.println(ld4);
        System.out.println(ld4-ld3);
    }
}

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 33 人打了分,平均分: 4.30 )
Loading...
程序员技术练级攻略

程序员技术练级攻略

注:该文最新的版本在这里 程序员技术练级攻略(2018版) (需要付费阅读)

月光博客6月12日发表了《 写给新手程序员的一封信 》,翻译自《 An open letter to those who want to start programming 》,我的朋友(他在本站的id是 Mailper )告诉我,他希望在酷壳上看到一篇更具操作性的文章。因为他也是喜欢编程和技术的家伙,于是,我让他把他的一些学习Python和Web编程的一些点滴总结一下。于是他给我发来了一些他的心得和经历,我在把他的心得做了不多的增改,并根据我的经历增加了“进阶”一节。 这是一篇由新手和我这个老家伙根据我们的经历完成的文章

我的这个朋友把这篇文章取名叫Build Your Programming Technical Skills,我实在不知道用中文怎么翻译,但我在写的过程中, 我觉得这很像一个打网游做任务升级的一个过程,所以取名叫“技术练级攻略”,题目有点大,呵呵,这个标题纯粹是为了好玩 这里仅仅是在分享Mailper和我个人的学习经历。 (注:省去了我作为一个初学者曾经学习过的一些技术(今天明显过时了),如:Delphi/Power builder,也省去了我学过的一些我觉得没意思的技术Lotus Notes/ActiveX/COM/ADO/ATL/.NET ……)

前言

你是否觉得自己从学校毕业的时候只做过小玩具一样的程序? 走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍(朋友的抱怨:学校课程总是从理论出发, 作业项目都看不出有什么实际作用,不如从工作中的需求出发)

建议:

  • 不要乱买书,不要乱追新技术新名词, 基础的东西经过很长时间积累而且还会在未来至少10年通用。
  • 回顾一下历史,看看历史上时间线上技术的发展,你才能明白明天会是什么样。
  • 一定要动手,例子不管多么简单, 建议至少自己手敲一遍看看是否理解了里头的细枝末节。
  • 一定要学会思考,思考为什么要这样,而不是那样。还要举一反三地思考。

:你也许会很奇怪为什么下面的东西很偏Unix/Linux,这是因为我觉得Windows下的编程可能会在未来很没有前途,原因如下:

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 317 人打了分,平均分: 4.74 )
Loading...
语言的数据亲和力

语言的数据亲和力

[ 感谢 Todd 同学 投递本文 ]

目前,程序设计语言似乎进入了一个蓬勃发展的时期,Javascript、Perl、Python、Ruby、Groovy等一批较新的语言正越来越多地被熟悉和使用,而C++、C#、Java等主流语言也在不断地融入函数式和动态性特征。程序员的百宝箱中可供选择的宝贝是越来多了,而社区中关于语言间的比较和争论也更为热烈,我们常常见到关于“面向过程和面向对象的比较”、“动态语言和静态语言的比较”、“命令式和函数式范式的比较”等比较。我注意到这类讨论的关注点多集中于设计相关话题,如“动态语言的Duck typing多态和静态语言的继承多态的比较”,“Prototype based和Class based的比较”等。但我认为还有一个十分重要的方面值得关注,这就是数据处理。

数据处理之所以重要是因为不论是本地信息存储还是系统间信息交换都需要建立在一定的数据格式基础上。另外,不管语言属于那种范式,设计上采用什么模式,在微观层次上程序很大一部分工作都是在做数据处理。所以,从数据处理角度比较和理解语言间的差异有重要的现实意义。虽然数据通常是平台和语言无关的,但不同的语言在处理某种格式的数据时会表现出不同的难度,甚至某些数据格式只能采用特定的语言才能实现,这就是数据亲和力的不同。

语言的数据亲和力(Data Affinity)指的是语言的数据模型与某种数据格式之间的匹配程度。语言对某种数据格式亲和力越强,则操作某类数据越容易。

二进制字节块格式

在偏底层的操作系统、嵌入式和通信系统中,二进制的字节块是最常见的一种数据格式。二进制数据布局紧凑和接近机器的特点使得它常常作为系统间通信或系统文件的数据格式,但一般高级语言都不方便直接和0101打交道,而是基于记录、结构体和类等结构化表示操作数据,这就存在着在底层的二进制字节块和高层的结构化数据直接的转换问题。

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 22 人打了分,平均分: 4.45 )
Loading...
如何写出无法维护的代码

如何写出无法维护的代码

酷壳里有很多我觉得很不错的文章,但是访问量最大的却是那篇《 6个变态的Hello World 》,和它能在本站右边栏“ 全站热门 ”中出现的还有“ 如何加密源代码 ”,以及 编程真难啊 等这样的文章。可见本站的读者们的偏好,我也相信你们都是“身怀绝技”的程序员。所以,今天给大家推荐这篇文章,相信一定能触动大家的兴奋点。

这篇文章的原文在这里( http://mindprod.com/jgloss/unmain.html ),我看完后我想说——

  1. 什么叫“创造力”,创造力就是——就算是要干一件烂事都能干得那么漂亮那么有创意的能力。
  2. 什么叫“抓狂”,抓狂就是——以一种沉着老练的不屈不挠的一本正经的精神一点一点把你推向崩溃的边缘

我把文章节选了一些,也并没有完全翻译,简译一下,也加入了一些自己的调侃。对于有下面这些编程习惯的朋友,请大家对号入座。另外,维护程序的朋友们,你们死定了!!

woodpecker If builders built buildings the way programmers write programs, then the first woodpecker that came along would destroy civilization. (如果建筑师盖房子就像程序员写程序一样,那么,第一只到来的啄木鸟就能毁掉我们的文明)

~ Gerald Weinberg (born: 1933-10-27 age: 77) Weinberg’s Second Law

程序命名

  • 容易输入的名字 。比如:Fred,asdf
  • 单字母的变量名 。比如:a,b,c, x,y,z(陈皓注:如果不够用,可以考虑a1,a2,a3,a4,….)
  • 有创意地拼写错误 。比如:SetPintleOpening, SetPintalClosing。这样可以让人很难搜索代码。
  • 抽象 。比如:ProcessData, DoIt, GetData… 抽象到就跟什么都没说一样。
  • 缩写 。比如:WTF,RTFSC …… (陈皓注:使用拼音缩写也同样给力,比如: BT,TMD,TJJTDS)
  • 随机大写字母 。比如:gEtnuMbER..
  • 重用命名 。在内嵌的语句块中使用相同的变量名有奇效。
  • 使用重音字母 。比如:int  ínt(注:第二个 ínt不是int)
  • 使用下划线 。比如:_, __, ___。
  • 使用不同的语言 。比如混用英语,德语,或是中文拼音。
  • 使用字符命名 。比如:slash, asterix, comma…
  • 使用无关的单词 。比如:god, superman, iloveu….
  • 混淆l和1 。字母l和数字1有时候是看不出来的。

阅读全文 Read More

好烂啊 有点差 凑合看看 还不错 很精彩 ( 67 人打了分,平均分: 4.42 )
Loading...