在markdown文件标题输入“#”

由于markdown文件是以“#”作为标题符号的,所以如果标题内容本身包含“#”,就不能直接输出。举个例子,如果标题是“C#”,输入“#C#”的话,效果如下:

C

可以看到“#”没有输出。

解决方式有两种:
(1)利用HTML语法,用“#”表示“#”,即输入“#C#” ;
(2)利用“\”,输入“#C\#”(要注意在“\”和“#”后面有一个空格,否则输出效果为“C\”)。
效果如下:

C#

参考资料:
(1)How to output “#” in title in mardkown file?

在Linux上搭建D语言开发环境

本文介绍如何在Linux上搭建D语言的开发环境:

(1)编译器我选的是gdc,从官方网站下载适合机器的版本,直接解压缩就可以了(不要解压到系统root文件夹:”/“)。为了方便起见,可以把路径加到PATH环境变量:

export PATH=$PWD/x86_64-gdcproject-linux-gnu/bin:$PATH

接下来写个简单的“hello world”程序(hello.d):

import std.stdio;
void main()
{
    writeln("Hello World!");
}  

编译一下:

[root@localhost nan]# gdc hello.d -o hello
/usr/bin/ld: unrecognized option '-plugin'
/usr/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status

这个问题的解决办法是在编译时加上“-fno-use-linker-plugin”选项。再次编译:

[root@localhost nan]# gdc -fno-use-linker-plugin -g hello.d -o hello
[root@localhost nan]# 

成功!
运行一下:

[root@localhost nan]# ./hello
Hello World!

输出了“Hello World!”。

(2)使用gdb进行调试。
示例程序代码如下:

import std.stdio;

void main()
{
    int sum;
    int i;

    for (i = 1; i <= 10; i++)
    {
        sum += i;
    }

    writeln(sum);
}

编译时需要加上“-g”编译选项,产生调试信息:

gdc -fno-use-linker-plugin -g sum.d -o sum

开始调试:

[root@localhost nan]# gdb -q sum
Reading symbols from sum...done.
(gdb) start
Temporary breakpoint 1 at 0x4057bf: file sum.d, line 5.
Starting program: /home/nan/sum
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Temporary breakpoint 1, D main () at sum.d:5
5               int sum;
(gdb) n
6               int i;
(gdb)
8               for (i = 1; i <= 10; i++)
(gdb)
10                      sum += i;
(gdb)
8               for (i = 1; i <= 10; i++)
(gdb) p i
$1 = 1
(gdb) p sum
$2 = 1
(gdb) c
Continuing.
55
[Inferior 1 (process 41619) exited normally]

可以看到,和调试普通的C程序没什么区别。

参考资料:
(1)How to fix “unrecognized option ‘-plugin`” when using gdc to compile D program?
(2)GDC documentation and debugging problems

Redis从2.8.12版本开始支持“ROLE”命令

今天才知道,Redis2.8.12版本开始支持“ROLE”命令了。通过“ROLE”命令,可以得到当前Redis的角色是“master”,“slave”或者“sentinel”。回想我们一年前做Redis监控程序时,还要通过“info”命令得到整个Redis状态,然后再解析“Role”这个关键字,才能得到是什么角色,实在有点麻烦。如果有机会,应该升级一下监控程序,一旦发现是2.8.12版本,就直接用“ROLE”命令好了。

100个gdb小技巧(v1.0).pdf

hellogcc于今年6月份开启《100个gdb小技巧》这个项目,我便参与其中。截至到这周末,一共收集了100个实用的gdb小技巧。我利用这个周末时间,把它制作成了一本pdf的电子书,方便大家下载和使用。当然,100不是终点,未来这个项目还会发展下去,还会有2.03.0的版本出来。Stay tuned!

P.S.:下载地址

unixODBC驱动链接的数据库客户端和程序直接链接的数据库客户端库一定要一致

这两天调试了一个诡异的问题,使用unixODBC连接MySQL数据库,最后程序core dumpMySQL client代码的fill_ird_data_lengths函数:

void fill_ird_data_lengths(DESC *ird, ulong *lengths, uint fields)
{
  ......
  assert(fields == ird->count);
}

fileds是一个很离谱的数,一看就像是内存值被破坏了。

经过艰苦的单步调试,最后查出的问题是unixODBC驱动链接的MySQL数据库客户端库和程序直接链接的MySQL数据库客户端库不一样(因为程序还没有完全改完,有一部分code还会直接调用MySQL数据库客户端库)。

这个坑一定要记住!

一键编译安装gcc

本文原载于我在hellogcc上的文章

今天看到一篇文章,作者通过一个shell脚本和一个Makefile,可以自动下载需要的所有安装包并且自动编译gcc

$ # Download the scripts using wget.
$ mkdir /opt/gcc-4.9.2
$ cd /opt/gcc-4.9.2
$ wget http://projects.joelinoff.com/gcc-4.9.2/bld.sh
$ wget http://projects.joelinoff.com/gcc-4.9.2/Makefile
$ chmod a+x bld.sh
$ make
[output snipped]
$ # The compiler is installed in /opt/gcc-4.9.2/rtf/bin

我试了一下,果然很方便。只要有一台可以联网的机器,就可以了。感兴趣的朋友可以试一试。

P.S.:
(1)编译libiconv时可能会有“'gets' undeclared here“错误,请参考这篇文章
(2)如果机器是64位的,但是缺少32位的库文件。这样在编译gcc时会出现错误:“configure: error: I suspect your system does not have 32-bit developement libraries (libc and headers). If you have them, rerun configure with --enable-multilib. If you do not have them, and want to build a 64-bit-only compiler, rerun configure with --disable-multilib.”。提示需要配置“--disable-multilib”。

ODBC中的三种变量类型

无论是使用ODBC的新手或老兵,看到SQLCHARSOL_C_CHARSQL_CHAR,可能都会有些糊涂。它们之间的区别到底是什么呢?

(1)第一种是ODBC定义的数据类型(像SQLCHAR):SQL开头,后面跟着一系列大写字符,但是没有下划线。这种数据类型定义在sqltypes.h中,比如:

typedef signed short int   SQLSMALLINT;
typedef SQLSMALLINT     SQLRETURN;

#if (ODBCVER >= 0x0300)
typedef void *                  SQLHANDLE; 
......
#endif

这种数据类型可以用来定义变量,ODBC API的变量类型都是这种类型:

#if (ODBCVER >= 0x0300)
    SQLRETURN  SQL_API SQLAllocHandle(SQLSMALLINT HandleType,
                                      SQLHANDLE InputHandle, SQLHANDLE *OutputHandle);
#endif

这样做的好处是ODBC提供了一套自己的变量类型,相当于封装了一层,使用者不用关心底层具体的变量类型实现细节。即使底层的变量类型做了修改,使用者的代码也不用做任何改动。
这种数据类型和C语言数据类型的映射如下:

ODBC 类型 C 类型
SQLCHAR char
SQLSCHAR signed char
SQLINTEGER long int

(2)第二种是C语言的数据类型编码(SQL_C_CHAR)。他们并不是真正的数据类型,而是针对上面提到的的ODBC定义的数据类型的编码,所以不能用来定义变量。他们可以用作ODBC API的参数。这种数据类型定义在sqlext.h中,比如:

#define SQL_C_CHAR    SQL_CHAR             /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG    SQL_INTEGER          /* INTEGER                      */
#define SQL_C_SHORT   SQL_SMALLINT         /* SMALLINT                     */
#define SQL_C_FLOAT   SQL_REAL             /* REAL                         */
#define SQL_C_DOUBLE  SQL_DOUBLE           /* FLOAT, DOUBLE                */

这种数据类型和ODBC数据类型的映射如下:

整数编码 ODBC 类型
SQL_C_CHAR SQLCHAR
SQL_S_STINYINT SQLSCHAR
SQL_C_SLONG SQLINTEGER

(3)第三种是SQL数据类型编码。同第二种一样,他们也不是真正的数据类型,而是提供SQL数据类型和编程语言数据类型的关联,因为也是数字编码,所以也不能用来定义变量。他们可以用作ODBC API的参数。这种数据类型定义在sqlext.h中,比如:

#define SQL_C_CHAR    SQL_CHAR             /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG    SQL_INTEGER          /* INTEGER                      */
#define SQL_C_SHORT   SQL_SMALLINT         /* SMALLINT                     */
#define SQL_C_FLOAT   SQL_REAL             /* REAL                         */
#define SQL_C_DOUBLE  SQL_DOUBLE           /* FLOAT, DOUBLE                */

这种数据类型和SQL数据类型的映射如下:

整数编码 SQL类型
SQL_CHAR Char(n)
SQL_VARCHAR Varchar(n)
SQL_SMALLINT Smallint

使用MySQL ODBC一次提交多条SQL语句

MySQL ODBC3.51.18版本开始支持一次提交多个语句(请参考:http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html)。方法是要给odbc.ini的数据源配置值为67108864option。如下图所示:

[DB1]
......
option = 67108864

注意这个option一定要配在odbc.ini的数据源上,而不能配在odbcinst.ini的驱动上。因为MySQLODBC代码只从odbc.ini文件查找option

int ds_lookup(DataSource *ds)
{
    ......
    for (used= 0; used < size; used += sqlwcharlen(entries) + 1,
                             entries += sqlwcharlen(entries) + 1)
      {
        int valsize;
        ds_map_param(ds, entries, &dest, &intdest, &booldest);

        if ((valsize= SQLGetPrivateProfileStringW(ds->name, entries, W_EMPTY,
                                                  val, ODBCDATASOURCE_STRLEN,
                                                  W_ODBC_INI)) < 0)
        {
          rc= 1;
          goto end;
        }
        else if (!valsize)
          /* skip blanks */;
        else if (dest && !*dest)
          ds_set_strnattr(dest, val, valsize);
        else if (intdest)
          *intdest= sqlwchartoul(val, NULL);
        else if (booldest)
          *booldest= sqlwchartoul(val, NULL) > 0;
        else if (!sqlwcharcasecmp(W_OPTION, entries))
          ds_set_options(ds, ds_get_options(ds) | sqlwchartoul(val, NULL));

        RESTORE_MODE();
      }

    ......
}

验证这个配置项是否成功,可以通过wireshark查看建立连接时的抓包:

捕获
可以看到“Multiple Statements”值为1,设置成功。

小评《理解Unix进程》

双“十一”期间参加CSDN活动,中了一本《理解Unix进程》,这两天花时间看完了。简单谈一下对这本书的的评价,谨代表个人意见。

这本书很薄,只有100来页,分为20章还有4节附录,这就表明每一章内容不是很多。书中的示例是用ruby语言写的,但是我相信大家都能看懂,不需要对ruby有很深的了解。总体来讲,这本书还是讲解了很多关于Unix的知识点,可以作为参考手册,或者可以在上下班的车上抽空读一读。不管是新手还是老兵,个人觉得都值得一看。价格也还好,20多元,应该不算贵。

另外,如果本身就是ruby程序员的,我非常推荐,应该会给你一些帮助!

在RedHat上快速安装gcc

今天需要在一台干净的RedHat上快速安装gcc,好能编译一些lib库。登录https://idp.redhat.com/idp/,下载了能找到的最高版本的安装包:cpp-3.2.3-60.x86_64.rpmgcc-3.2.3-60.x86_64.rpm,安装一气呵成:

[root@localhost nan]# rpm -ivh cpp-3.2.3-60.x86_64.rpm
warning: cpp-3.2.3-60.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID db42a60e: NOKEY
Preparing...            ########################################### [100%]
   1:cpp                ########################################### [100%]
[root@localhost nan]# rpm -ivh gcc-3.2.3-60.x86_64.rpm 
warning: gcc-3.2.3-60.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID db42a60e: NOKEY
Preparing...            ########################################### [100%]
   1:gcc                ########################################### [100%]

验证一下:

[root@localhost nan]# gcc -v
Reading specs from /usr/lib/gcc-lib/x86_64-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=x86_64-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-60)

尽管版本有点低,最起码现在有个能用的gcc了。如果需要高版本,再用这个gcc编译吧。