月度归档:2014年04月

C语言的整型溢出问题

整型溢出有点老生常谈了,bla, bla, bla… 但似乎没有引起多少人的重视。整型溢出会有可能导致缓冲区溢出,缓冲区溢出会导致各种黑客攻击,比如最近OpenSSL的heartbleed事件,就是一个buffer overread的事件。在这里写下这篇文章,希望大家都了解一下整型溢出,编译器的行为,以及如何防范,以写出更安全的代码。

什么是整型溢出

C语言的整型问题相信大家并不陌生了。对于整型溢出,分为无符号整型溢出和有符号整型溢出。

对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”,也就是说,如果一个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模。例如:

unsigned char x = 0xff;
printf("%d\n", ++x);

上面的代码会输出:0 (因为0xff + 1是256,与2^8求模后就是0)

对于signed整型的溢出,C的规范定义是“undefined behavior”,也就是说,编译器爱怎么实现就怎么实现。对于大多数编译器来说,算得啥就是啥。比如:

signed char x =0x7f; //注:0xff就是-1了

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

C语言的整型溢出问题

整型溢出有点老生常谈了,bla, bla, bla… 但似乎没有引起多少人的重视。整型溢出会有可能导致缓冲区溢出,缓冲区溢出会导致各种黑客攻击,比如最近OpenSSL的heartbleed事件,就是一个buffer overread的事件。在这里写下这篇文章,希望大家都了解一下整型溢出,编译器的行为,以及如何防范,以写出更安全的代码。

什么是整型溢出

C语言的整型问题相信大家并不陌生了。对于整型溢出,分为无符号整型溢出和有符号整型溢出。

对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”,也就是说,如果一个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模。例如:

unsigned char x = 0xff;
printf("%d\n", ++x);

上面的代码会输出:0 (因为0xff + 1是256,与2^8求模后就是0)

对于signed整型的溢出,C的规范定义是“undefined behavior”,也就是说,编译器爱怎么实现就怎么实现。对于大多数编译器来说,算得啥就是啥。比如:

signed char x =0x7f; //注:0xff就是-1了

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

从LongAdder看更高效的无锁实现

(感谢 @jd刘锟洋 投稿,更多文章参看他的博客:码梦为生

原文链接:《比AtomicLong还高效的LongAdder 源码解析

接触到AtomicLong的原因是在看guava的LoadingCache相关代码时,关于LoadingCache,其实思路也非常简单清晰:用模板模式解决了缓存不命中时获取数据的逻辑,这个思路我早前也正好在项目中使用到。

言归正传,为什么说LongAdder引起了我的注意,原因有二:

  1. 作者是Doug lea ,地位实在举足轻重。
  2. 他说这个比AtomicLong高效。

我们知道,AtomicLong已经是非常好的解决方案了,涉及并发的地方都是使用CAS操作,在硬件层次上去做 compare and set操作。效率非常高。

因此,我决定研究下,为什么LongAdder比AtomicLong高效。

首先,看LongAdder的继承树:

la1

继承自Striped64,这个类包装了一些很重要的内部类和操作。稍候会看到。

正式开始前,强调下,我们知道,AtomicLong的实现方式是内部有个value 变量,当多线程并发自增,自减时,均通过CAS 指令从机器指令级别操作保证并发的原子性。

再看看LongAdder的方法:

la2
怪不得可以和AtomicLong

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

从Code Review 谈如何做技术

(这篇文章缘由我的微博,我想多说一些,有些杂乱,想到哪写到哪)

这两天,在微博上表达了一下Code Review的重要性。因为翻看了阿里内部的Review Board上的记录,从上面发现Code Review做得好的是一些比较偏技术的团队,而偏业务的技术团队基本上没有看到Code Review的记录。当然,这并不能说没有记录他们就没有做Code Review,于是,我就问了一下以前在业务团队做过的同事有没有Code Review,他告诉我不但没有Code Review,而且他认为Code Review没用,因为:

1)工期压得太紧,时间连coding都不够,以上线为目的,

2)需求老变,代码的生命周期太短。所以,写好的代码没有任何意义,烂就烂吧,反正与绩效无关。

我心里非常不认同这样的观点,我觉得我是程序员,我是工程师,就像医生一样,不是把病人医好就好了,还要对病人的长期健康负责。对于常见病,要很快地医好病人很简单,下猛药,大量使用抗生素,好得飞快。但大家都知道,这明显是“饮鸩止渴”、“竭泽而渔”的做法。医生需要有责任心和医德,我也觉得程序员工程师也要有相应的责任心和相应的修养。东西交给我我必需要负责,我觉得这种负责和修养不是”做出来“就了事了,而是要到“做漂亮”这个级别,这就是“山

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

从Code Review 谈如何做技术

(这篇文章缘由我的微博,我想多说一些,有些杂乱,想到哪写到哪)

这两天,在微博上表达了一下Code Review的重要性。因为翻看了阿里内部的Review Board上的记录,从上面发现Code Review做得好的是一些比较偏技术的团队,而偏业务的技术团队基本上没有看到Code Review的记录。当然,这并不能说没有记录他们就没有做Code Review,于是,我就问了一下以前在业务团队做过的同事有没有Code Review,他告诉我不但没有Code Review,而且他认为Code Review没用,因为:

1)工期压得太紧,时间连coding都不够,以上线为目的,

2)需求老变,代码的生命周期太短。所以,写好的代码没有任何意义,烂就烂吧,反正与绩效无关。

我心里非常不认同这样的观点,我觉得我是程序员,我是工程师,就像医生一样,不是把病人医好就好了,还要对病人的长期健康负责。对于常见病,要很快地医好病人很简单,下猛药,大量使用抗生素,好得飞快。但大家都知道,这明显是“饮鸩止渴”、“竭泽而渔”的做法。医生需要有责任心和医德,我也觉得程序员工程师也要有相应的责任心和相应的修养。东西交给我我必需要负责,我觉得这种负责和修养不是”做出来“就了事了,而是要到“做漂亮”这个级别,这就是“山

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

NHibernate 中使用 nvarchar(max) 类型 – 冠军

在 NHibernate 中使用字符串类型,默认会映射到字符类型,在 SQLServer 中,NVARCHAR 类型最大长度是 4000 字符,如果超过 4000,比如使用 SQL Server 中的 nvarchar(max),那么就需要特别配置。

比如说,我们在实体中定义了一个名为 Content 的字段。

public virtual string Content { set; get; }

默认情况下,对应的数据库字段定义会自动生成为

Content NVARCHAR(255) null

如果我们希望它的长度是 NVARCHAR(MAX) 怎么办呢?

很容易找到的说明是使用 StringClob 类型,这是 NHibernate 内部定义的一个类型,用来说明这个字段是一个长字符串类型,你的字段属性是字符串类型?没有问题,NHibernate 知道这一点的,你完全不用修改你的实体定义。

<property name=”Content” type=”StringClob” />

那么,你就会看到现在对应的数据库字段定义修改为了你的目标。

Content NVARCHAR(MAX) null

 StringClob 太诡异了,你不想使用这个办法,其实也可以直接指定数据库中的字段类

阅读全文

本条目发布于。属于.NetWEB分类。作者是
分享到:

NHibernate 中使用 nvarchar(max) 类型 – 冠军

在 NHibernate 中使用字符串类型,默认会映射到字符类型,在 SQLServer 中,NVARCHAR 类型最大长度是 4000 字符,如果超过 4000,比如使用 SQL Server 中的 nvarchar(max),那么就需要特别配置。

比如说,我们在实体中定义了一个名为 Content 的字段。

public virtual string Content { set; get; }

默认情况下,对应的数据库字段定义会自动生成为

Content NVARCHAR(255) null

如果我们希望它的长度是 NVARCHAR(MAX) 怎么办呢?

很容易找到的说明是使用 StringClob 类型,这是 NHibernate 内部定义的一个类型,用来说明这个字段是一个长字符串类型,你的字段属性是字符串类型?没有问题,NHibernate 知道这一点的,你完全不用修改你的实体定义。

<property name=”Content” type=”StringClob” />

那么,你就会看到现在对应的数据库字段定义修改为了你的目标。

Content NVARCHAR(MAX) null

 StringClob 太诡异了,你不想使用这个办法,其实也可以直接指定数据库中的字段类

阅读全文

本条目发布于。属于.NetWEB分类。作者是
分享到:

C语言结构体里的成员数组和指针

单看这文章的标题,你可能会觉得好像没什么意思。你先别下这个结论,相信这篇文章会对你理解C语言有帮助。这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接。微博截图如下。我觉得好多人对这段代码的理解还不够深入,所以写下了这篇文章。

zero_array

为了方便你把代码copy过去编译和调试,我把代码列在下面:

#include <stdio.h>
struct str{
    int len;
    char s[0];
};

struct foo {
    struct str *a;
};

int main(int argc, char** argv) {
    struct foo f={0};
    if (f.a->s) {
        printf( f.a->s);
    }
    return 0;
}

你编译一下上面的代码,在VC++和GCC下都会在14行的printf处crash掉你的程序。@Laruence 说这个是个经典的坑,我觉得这怎么会是经典的坑呢?上面这代码,你一定会问,为什么if语句判断的不是f.a?而是f.a里面的数组?写这样代码的人脑子里在想什么?还是用这样的代码来玩票?不管怎么样,我

阅读全文

本条目发布于。属于开发分类。作者是
分享到:

C语言结构体里的成员数组和指针

单看这文章的标题,你可能会觉得好像没什么意思。你先别下这个结论,相信这篇文章会对你理解C语言有帮助。这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接。微博截图如下。我觉得好多人对这段代码的理解还不够深入,所以写下了这篇文章。

zero_array

为了方便你把代码copy过去编译和调试,我把代码列在下面:

#include <stdio.h>
struct str{
    int len;
    char s[0];
};

struct foo {
    struct str *a;
};

int main(int argc, char** argv) {
    struct foo f={0};
    if (f.a->s) {
        printf( f.a->s);
    }
    return 0;
}

你编译一下上面的代码,在VC++和GCC下都会在14行的printf处crash掉你的程序。@Laruence 说这个是个经典的坑,我觉得这怎么会是经典的坑呢?上面这代码,你一定会问,为什么if语句判断的不是f.a?而是f.a里面的数组?写这样代码的人脑子里在想什么?还是用这样的代码来玩票?不管怎么样,我

阅读全文

本条目发布于。属于开发分类。作者是
分享到: