Work at Home This Week

| Comments

这个星期由于脚被烫伤不能走路,于是享受了一下向往已久的”work at home”待遇。我总结了一些优缺点如下:

优点

  • 由于不用去公司,每天上下班路程上耗费的一个半小时省出来可以做点其他事情。
  • 可以选择性的去干干家务什么的,工作生活两不误,还可以放松放松大脑,一天下来不会觉得那么累。:)
  • 可以大声放音乐不用戴耳机,不过这个还真不适合我,有音乐在我永远进入不了那种Zen的状态。

缺点

  • 咖啡!最先怀念的就是那台咖啡机啦,没有咖啡总觉得少了点什么,咖啡才是第一生产力啊!
  • 最大的问题是沟通,稍微复杂点的问题用文字沟通效率非常低,所以有时候还得靠电话。
  • 分心的事情比较多,整个人比较放松,不适合做目的性不太明确的工作。但是适应一两天后这个情况有所改善。
  • 由于工作基本上还是得用公司电脑,远程连接毕竟没有直接操作来得顺畅,所以效率上会低一些。

总的来说我还是比较喜欢公司的气氛,一个人在家真是闷得慌,偶尔这样一下调剂生活倒是不错。当然这个只是针对我而言,也有人更喜欢在家的那种感觉。我觉得在家工作比较适合那种一个人项目,比如我自己随便玩玩的那些东西,真正的团队合作还是得在一起,要不沟通的成本会大大超出在家工作的那些好处。

C++任意指针转换为object指针

| Comments

最近碰到一个C++指针转换的问题,发现颇有意思,值得记录一下。 有一个foo class如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class foo
{
public:
    int get_foo(int val);

    int m_foo;
};

int foo::get_foo(int val)
{
    int a = 345;
    int rc = val + a;
    cout << rc << endl;
    return rc;
}

测试如下

1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
    int* val = new int[100];

    foo* foo_ptr;
    foo_ptr = (foo*)val;
    foo_ptr->get_foo(100);
    foo_ptr->m_foo = 101;
    cout << foo_ptr->m_foo << endl;

    return 0;
}

以上代码编译后运行竟然完全正常,太奇怪了!强制将任意一个指针转换成对象指针,然后调用它的方法和成员变量竟然可以正常执行。为此我去stackoverflow求助了一下,再经过和同事讨论,得出了如下结果:

  • 尽管这个指针实际不是指向的一个foo对象,但是当编译器把它当作一个foo对象来处理时,调用他的方法其实是调用foo class的方法,属于所有object都公用,如果该方法不是个虚函数也没有用到成员变量,这样做应该是没有问题的。

  • 如果Foo class里有虚函数,那么foo对象里会包含一个指向虚函数表的指针1,调用这个虚函数时会先用这个指针找到vtable,这里foo对象的虚函数表指针应该是val指针指向内存的后面某个位置,而这个位置的数据是不确定的,有很大可能指向的是一个非法访问地址,导致程序崩溃。

  • 访问成员变量在上面行得通是因为我为val分配了一段内存,foo对象访问成员m_foo其实是访问val这段内存的某个位置,修改这段内存不会有什么问题。如果val这样定义:int *val;, 那foo访问成员时行为就很不确定,运气不好,访问到允许的地址,修改了那里的值,问题过很久以后才显现出来。运气好,访问到非法地址,程序立即崩溃,这时出问题的地方离产生问题的地方很近。

最后引用下stackoverflow里很有意思的一个回复 :)

C++ lets you get away with doing things that aren’t allowed, under the name undefined behaviour. Basically, it means “if you do something stupid, we won’t stop you, but absolutely anything could happen”!

Emacs执行shell命令的问题

| Comments

今天在配置emacs的markdown-mode时调用C-c C-c p(转换成html然后在浏览器里打开预览)一直提示/bin/bash: markdown: command not found,它需要一个shell命令能将markdown转换成html,这里我用到了一个python的markdown库。

安装完在我的机器上是这个路径: /Library/Frameworks/Python.framework/Versions/Current/bin/markdown_py

接下来在/usr/bin创建一个markdown的软链接到markdown_py

1
sudo ln -s /Library/Frameworks/Python.framework/Versions/Current/bin/markdown_py /usr/bin/markdown

做完上面这些后在emacs里调用C-c C-c p还是提示同样的错误,但是markdown在我的本地终端可以执行。Google了下之后发现这可能是由于emacs在启动一个shell的时候不会去读取.bash_profile,这个文件只是在登陆的时候被读取一次。而我在.bashrc里没有做任何关于环境变量的设置,所以/usr/bin没有被加到PATH里去,导致bash找不到markdown这条命令。

等我把下面这句加到.bashrc

1
2
3
if [ -f ~/.bash_profile ]; then
. ~/.bash_profile
fi

问题还是没有解决,提示同样的错误。继续Google, 最后终于在这里找到答案。emacs直接执行shell命令默认是非交互式的,所以不会去读取.bashrc文件的。解决的办法就是在.emacs初始化文件里加上这句。

1
(setq shell-command-switch "-ic")

-i指定bash启动是交互式的, 然后才会去读取.bashrc。或者你也可以配置BASH_ENV, 单独为非交互式的shell指定启动脚本。-c表示命令读取来自字符串。

以上统统搞定终于写出了我的第一篇博客!哈哈