又是空指针惹的祸

(以下纯属一派胡言)

虽然在C99的文档中写,”The macros are NULL which expands to an implementation-defined null pointer constant; and…”.文档中说,实现者只要保证任何一个有效的对象的指针、函数指针都不等于NULL,至于它实际等于哪个整数,那是由实现者来决定的。可是如果NULL不等于0,

if(fp) fread(buf,1,nbytes,fp)

将是一段看起来很奇怪的代码。它会正确吗?

几乎所有人都默认,如果p==NULL,那么*p一定会导致程序崩溃,后面的代码不会被执行。可这依赖于OS和CPU将地址空间最底端的那个页设置成不可读。下面这样的代码有效吗?

struct dirent p=NULL;
char* name=p->d_name;

如果你认为它无效,那么freebsd下offsetof的实现将是极度令你吃惊的:

#define __offsetof(type, field) ((size_t)(&((type *)0)->field))

我把C99的文档仔细的翻阅了一遍,它没有说这样不可以。然后我再查了下vc9的stddef.h,它也是用同样的方式实现的。

可我们过度聪明的gcc 犯糊涂了:
http://patchwork.kernel.org/patch/34190/

    struct tun_file *tfile = file->private_data;
    struct tun_struct *tun = __tun_get(tfile);
    struct sock *sk = tun->sk;
    unsigned int mask = 0;
    if (!tun)
       return POLLERR;

linux的某个版本的gcc在优化的时候,把if那句给优化掉了!理由是tun这个指针在前面已经被用过。

我写了段测试代码:

#include <locale.h>
#if defined(FreeBSD)
#include <sys/dirent.h>
#else
#include <dirent.h>
#endif
#include <stdio.h>
#include <string.h>

void myfunc(struct dirent* p){
  char* name=p-&gt;d_name;
  if(!p){
    printf("p==NULL,name=%x\n",name);
    return ;
  }
  printf("p!=NULL\n");
}

int main (int argc,char* argv[]){
  setlocale(LC_ALL,"");
  if(argc&gt;1)
    myfunc(NULL);
  else {
    struct dirent dir;
    memset(&amp;dir,0,sizeof(dir));
    myfunc(&amp;dir);
  }
  return 0;
}

在freebsd下分别用gcc 4.2.1和gcc 4.4.1 测试,均未能重现gcc那个传说中的bug。换到ubuntu下用4.2.4测试,还是未能重现该BUG

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥