XNERV SURVEYS

God's in his heaven.
All's right with the world.

0%

volatile

  • volatile使得代码每次在读写volatile变量时都需要从内存读写,而不能使用寄存器中缓存的值。并且也禁止编译器对volatible做编译优化。volatile本身并不是用于线程同步,也不保证原子读写(例如volatile a++这种需要几个指令才能完成的操作)。volatile主要用于access to memory mapped devices和variables in signal handlers and between setjmp and longjmp。C++标准禁止编译器reorder同一个线程内的volatile变量的读写,但不同线程则没有限制。non-volatile变量则有可能发生reorder(Stay away from Volatile in threaded code?)。
  • 而根据为什么volatile++不是原子性的?中的说法,volatile的读操作后会插入LoadLoad和LoadStore屏障,避免volatile读操作与后面的普通读写发生reorder。而volatile的写操作前会插入StoreLoad和StoreStore屏障,避免volatile写操作与后面的普通读写发生reorder(我不太确定这种说法的正确性,毕竟在wikipediavolatile (computer programming)中并没有提到volatile会插入内存屏障,或者只有Java等语言才会这样做?)。
  • 内存屏障中有提到

    C与C++语言中,volatile关键字意图允许内存映射的I/O操作。这要求编译器对此的数据读写按照程序中的先后顺序执行,不能对volatile内存的读写重排序。因此关键字volatile并不保证是一个内存屏障。[4]
    对于Visual Studio 2003,编译器保证对volatile的操作是有序的,但是不能保证处理器的乱序执行。因此,可以使用InterlockedCompareExchange或InterlockedExchange函数。
    对于Visual Studio 2005及以后版本,编译器对volatile变量的读操作使用acquire semantics,对写操作使用release semantics。

阅读全文 »

本文是关于大学时一些常见的数据结构、算法和知识点的总结。其实与其说工作中会用到,不如说面试时被面到的可能性更大一些。不过其中一些特定领域的算法,像银行家算法,BAT的面试中我也还没有遇到过。适当地回顾大学时学到的一些知识点,也许能给自己带来一些快乐吧,一种仅存在于回忆中的快乐。

阅读全文 »

Python的初学者(以及很多熟练工)相信都遇到过下面的运行时错误信息:

UnicodeDecodeError: ‘ASCII’ codec can’t decode byte 0xe4 in position 0: ordinal not in range(128)

然后百度一下发现说明这个问题的网页有一大把,基本无非是下面两种解决方案:

  1. 在Python文件的开头加一句#coding=utf-8
  2. 在代码中加入:
1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf8')

一般大家的做法是把两者都加上,然后问题一般也会得到解决。但很少有人会去深究过Python会什么会产生这样的编码问题,以及为什么通过加上面的代码可以解决这个问题。作为一个合格的程序员,遇到这种问题就应该追根究底 :)

阅读全文 »

fork

关于linux进程间的close-on-exec机制

一般我们会调用exec执行另一个程序,此时会用全新的程序替换子进程的正文,数据,堆和栈等。此时保存文件描述符的变量当然也不存在 了,我们就无法关闭无用的文件描述符了。所以通常我们会fork子进程后在子进程中直接执行close关掉无用的文件描述符,然后再执行exec。
但是在复杂系统中,有时我们fork子进程时已经不知道打开了多少个文件描述符(包括socket句柄等),这此时进行逐一清理确实有很大难 度。我们期望的是能在fork子进程前打开某个文件句柄时就指定好:“这个句柄我在fork子进程后执行exec时就关闭”。其实时有这样的方法的:即所 谓 的 close-on-exec。
回到我们的应用场景中来,只要我们在创建socket的时候加上 SOCK_CLOEXEC标志,就能够达到我们要求的效果,在fork子进程中执行exec的时候,会清理掉父进程创建的socket。

阅读全文 »

英文版本 Everything You Never Wanted To Know About DLLs.


最近因为一些原因,我需要调研动态链接在Windows平台上的实现细节。这篇文章主要是总结我在这个问题上所学到的知识,用于我将来的回顾和参考,但同时我也希望这篇文章对其他人所有帮助,因为我将要总结的这些内容,你可能需要东找西找才能找到。

废话不多说,让我们开始这趟旅程吧:

阅读全文 »

IOCP wiki

使用CreateIoCompletionPort函数创建IOCP,还可以把socket或文件句柄与IOCP关联起来。
一个线程,第一次调用GetQueuedCompletionStatus函数时,该线程变为关联了该IOCP的线程,直道下述三种情形之一发生:

  • 该线程退出;
  • 该线程调用GetQueuedCompletionStatus函数关联到其他的IOCP;
  • 该IOCP被关闭。

即,一个线程在任何时刻最多关联一个IOCP。

阅读全文 »

基础语法

  • 由于C++的枚举不像C#中的枚举,其枚举类型名并不是标识符的一部分,因此经常可能发生命名冲突的问题,解决的方法有四个:在枚举元素名称前加限定前缀(如enum EnumFruit { EnumFruit_apple = 1 };),将枚举类型放在一个同名的命名空间中,或将枚举作为类的嵌套类型,或者使用C++11的enum class(What’s an enum class and why should I care?)。
  • struct和class的默认类继承方式都是private,这与struct的成员默认继承方式是public是不同的。
  • #include_next <filename.h>,include位于搜索路径中位于当前文件之后的文件filename.h。
  • 在vc中,inlucde的路径的反斜杠不需要转义,如#include "..\..\..\Global\Data\GlobalPreferencesMgr.h"
  • 对于namespace中的函数或class的前置声明,必须同样也包括在相同的namespace中,而不能用class ::std::A这种写法。(Why can’t I forward-declare a class in a namespace like this?
  • 没有&&=,只有&=
  • (-1 || 0) == 1,请想想为什么。
阅读全文 »

For the chinese translated version, please click 关于DLL的一些你不会想要知道的知识.


I’ve recently had cause to investigate how dynamic linking is implemented on Windows. This post is basically a brain dump of everything I’ve learnt on the issue. This is mostly for my future reference, but I hope it will be useful to others too as I’m going to bring together lots of information you would otherwise have to hunt around for.

Without further ado, here we go:

阅读全文 »