﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-金庆的专栏-随笔分类-4. Linux/Unix</title><link>http://www.cppblog.com/jinq0123/category/5139.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 14 Jun 2018 00:15:15 GMT</lastBuildDate><pubDate>Thu, 14 Jun 2018 00:15:15 GMT</pubDate><ttl>60</ttl><item><title>etcd+registrator+confd 服务发现</title><link>http://www.cppblog.com/jinq0123/archive/2018/06/13/215722.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 13 Jun 2018 06:27:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2018/06/13/215722.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/215722.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2018/06/13/215722.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/215722.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/215722.html</trackback:ping><description><![CDATA[<div>etcd+registrator+confd 服务发现<br /><br />(金庆的专栏 2018.6)<br /><br />因为k8s使用 etcd, 所以选 etcd 作为服务发现的 DB.<br /><br />registrator 可以为 docker 方式运行的服务自动注册到 etcd.<br /><br />confd 读取 etcd, 生成配置文件。<br /><br />先运行一个etcd用于测试：<br /><br /><span style="color: #0000ff;">docker run -d \</span><br /><span style="color: #0000ff;">&nbsp; -p 12379:2379 \</span><br /><span style="color: #0000ff;">&nbsp; --name jinqing-etcd \</span><br /><span style="color: #0000ff;">&nbsp; quay.io/coreos/etcd \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp; /usr/local/bin/etcd \</span><br /><span style="color: #0000ff;">&nbsp; --listen-client-urls http://0.0.0.0:2379 \</span><br /><span style="color: #0000ff;">&nbsp; --advertise-client-urls http://0.0.0.0:12379 </span><br /><br />再运行 registrator:<br /><br /><span style="color: #0000ff;">docker run -d --rm \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; --name=jinqing-registrator \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; --net=host \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; --volume=/var/run/docker.sock:/tmp/docker.sock \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; gliderlabs/registrator:latest \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -ip="192.168.93.183" \</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; etcd://127.0.0.1:12379/registrator</span><br /><br />好像只能使用本机的 etcd. 一般需要用-ip参数指定本机IP。注册到 registrator 目录。<br /><br />用 etcdkeeper 可以查看自动注册的服务。registrator 不支持 etcd v3.</div><div><img src="http://www.cppblog.com/images/cppblog_com/jinq0123/etcdkeeper.png" alt="" width="1119" height="509" /></div><div><br />然后配置 confd<br /><br /><span style="color: #0000ff;">mkdir -p /etc/confd/{conf.d,templates}</span><br /><br />/etc/confd/conf.d/myconfig.toml<br /><br /><span style="color: #800000;">[template]</span><br /><span style="color: #800000;">src = "services.toml.tmpl"</span><br /><span style="color: #800000;">dest = "/tmp/services.toml"</span><br /><span style="color: #800000;">keys = [</span><br /><span style="color: #800000;">&nbsp;&nbsp;&nbsp; "/registrator",</span><br /><span style="color: #800000;">]</span><br /><br />/etc/confd/templates/services.toml.tmpl<br /><br /><span style="color: #800000;">[config]</span><br /><span style="color: #800000;">{{- range lsdir "/registrator"}}</span><br /><span style="color: #800000;">{{-&nbsp;&nbsp;&nbsp;&nbsp; $serviceName := . }}</span><br /><span style="color: #800000;">{{-&nbsp;&nbsp;&nbsp;&nbsp; $serviceDir := printf "/registrator/%s/*" $serviceName }}</span><br /><br /><span style="color: #800000;">&nbsp;&nbsp;&nbsp; [config.{{ $serviceName }}]</span><br /><span style="color: #800000;">&nbsp;&nbsp;&nbsp; # {{ $serviceDir }}</span><br /><br /><span style="color: #800000;">{{-&nbsp;&nbsp;&nbsp;&nbsp; range gets $serviceDir }}</span><br /><span style="color: #800000;">&nbsp;&nbsp;&nbsp; {{ base .Key }} = {{ .Value }}</span><br /><span style="color: #800000;">{{-&nbsp;&nbsp;&nbsp;&nbsp; end }}</span><br /><br /><span style="color: #800000;">{{- end}}</span><br /><br /><span style="color: #800000;"># End of [config].</span><br /><br />用 lsdir 列出所有服务目录，然后用 gets 取服务目录下的键值对。<br /><br />执行 confd:<br /><br /><span style="color: #0000ff;">~/go/bin/confd -onetime -backend etcd -node http://127.0.0.1:12379</span><br /><br /><span style="color: #0000ff;">[jinqing@localhost confd]$ cat /tmp/services.toml</span><br /><span style="color: #0000ff;">[config]</span><br /><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [config.etcd-2379]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; # /registrator/etcd-2379/*</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; localhost.tech:jinqing-etcd:2379 = 192.168.93.183:12379</span><br /><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [config.nginx]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; # /registrator/nginx/*</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; localhost.tech:jinqing-nginx:80 = 192.168.93.183:1024</span><br /><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; [config.registry]</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; # /registrator/registry/*</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; localhost.tech:registry:5000 = 192.168.93.183:5000</span><br /><br /><span style="color: #0000ff;"># End of [config].</span><br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/215722.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2018-06-13 14:27 <a href="http://www.cppblog.com/jinq0123/archive/2018/06/13/215722.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用docker stack开启redis集群</title><link>http://www.cppblog.com/jinq0123/archive/2017/10/26/215308.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 26 Oct 2017 04:08:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2017/10/26/215308.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/215308.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2017/10/26/215308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/215308.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/215308.html</trackback:ping><description><![CDATA[<div>用docker stack开启redis集群<br /><br />(金庆的专栏 2017.10)<br /><br />有5个docker swarm节点，开启redis cluster.<br />每个机器上开2个redis节点，共10个redis节点。<br />采用官方的redis:alpine镜像。<br /><br />docker-stack.yml 如下：<br /><br /><span style="color: #800000; font-family: Courier;">version: "3"</span><br /><span style="color: #800000; font-family: Courier;">services:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp; redis001:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; image: redis:alpine</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; volumes:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - /home/redis/001/data:/data</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - /home/redis/001/conf:/conf</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; command: redis-server --appendonly yes --cluster-enabled yes --cluster-config-file /conf/nodes.conf --cluster-announce-ip 10.240.79.8 --cluster-announce-port 7001 --cluster-announce-bus-port 17001</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; ports:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - "7001:6379"</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - "17001:16379"</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; networks:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - redisnet</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; deploy:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; placement:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; constraints:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - node.hostname == host-10-240-79-8</span><br /><br /><span style="color: #800000; font-family: Courier;">&nbsp; redis002:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; image: redis:alpine</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; volumes:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - /home/redis/002/data:/data</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - /home/redis/002/conf:/conf</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; command: redis-server --appendonly yes --cluster-enabled yes --cluster-config-file /conf/nodes.conf --cluster-announce-ip 10.240.79.9 --cluster-announce-port 7002 --cluster-announce-bus-port 17002</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; ports:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - "7002:6379"</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - "17002:16379"</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; networks:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - redisnet</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; deploy:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; placement:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; constraints:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - node.hostname == host-10-240-79-9</span><br /><br /><span style="color: #800000; font-family: Courier;">&nbsp; redis003:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp; ...</span><br /><span style="color: #800000; font-family: Courier;">&nbsp; redis010:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; ...</span><br />&nbsp; <br /><span style="color: #800000; font-family: Courier;">networks:</span><br /><span style="color: #800000; font-family: Courier;">&nbsp; redisnet:</span><br /><br />数据保存文件在 /home/redis/001/data<br />集群配置文件将保存到 /home/redis/001/conf/nodes.conf &nbsp;<br />各机器上目录需要预先创建，不然docker开启失败。<br />并且需要设置目录权限，不然报"Permission denied".<br />redis-server以用户uid=100(redis)运行，所以<br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; chown -R 100 /home/redis/</span><br /><br />启动redis服务栈:<br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; docker stack deploy -c docker-stack.yml redis</span><br /><br />redis-server启动后，运行 redis-trib.rb 来组建 redis cluster:<br /><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp; docker run --rm -it inem0o/redis-trib create --replicas 1 10.240.79.8:7001 10.240.79.9:7002 ... 10.240.79.12:7010</span><br /><br />注意 inem0o/redis-trib 的说明中，命令示例缺少 "-it", 会报错退出：<br /><span style="color: #0000ff;">Can I set the above configuration? (type 'yes' to accept): : undefined method `chomp' for nil:NilClass (NoMethodError)</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from /usr/bin/redis-trib:1295:in `create_cluster_cmd'</span><br /><span style="color: #0000ff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from /usr/bin/redis-trib:1701:in `&lt;main&gt;'</span><br /><br />运行 redis-cli 测试，"-c" 参数表示集群，可连接任意机器的7001-7010任意端口：<br /><span style="color: #0000ff;">[root@host-10-240-79-9 ~]# docker run -it --rm redis:alpine redis-cli -h 10.240.79.8 -p 7006 -c</span><br /><span style="color: #0000ff;">10.240.79.8:7006&gt; get a</span><br /><span style="color: #0000ff;">-&gt; Redirected to slot [15495] located at 10.240.79.10:7003</span><br /><span style="color: #0000ff;">(nil)</span><br /><br />用swarm mode开启redis服务比较方便。<br />但是出于性能考虑，应该禁用 swarm 的NAT转发和负载均衡。<br />研究了下，暂时还没学会。<br /><br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/215308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2017-10-26 12:08 <a href="http://www.cppblog.com/jinq0123/archive/2017/10/26/215308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CentOS升级Svn到最新版</title><link>http://www.cppblog.com/jinq0123/archive/2015/04/23/210429.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 23 Apr 2015 08:54:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2015/04/23/210429.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/210429.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2015/04/23/210429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/210429.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/210429.html</trackback:ping><description><![CDATA[<div>CentOS升级Svn到最新版<br />(金庆的专栏)<br /><br />CentOS/RHEL yum 安装的 subversion 是 1.6.11 版本，<br />连VisulaSVN服务器时会有"<span style="color:#FF0000;">Key usage violation</span>"：<br /><br /><span style="color:#000099;">[jinq@jinqing-centos ~]$ svn co https://.../server<br />svn:  OPTIONS of 'https://.../server': SSL handshake failed: SSL error: Key  usage violation in certificate has been detected. (https://...)<br /></span><br />subversion升级到最新版可解决该错误。<br /><br />Install Subversion 1.8.9 ( SVN Client ) on CentOS/RHEL <br />Thanks to Wandisco, which is maintaining the rpm packages for latest Subversion version. <br />( http://tecadmin.net/install-subversion-1-8-on-centos-rhel/ )<br /><br />按指示设置新的yum源，然后安装.<br /><br /><span style="color:#000099;">[jinq@jinqing-centos ~]$ svn --version<br />svn, version 1.8.13 (r1667537)<br />&nbsp;&nbsp; compiled Apr&nbsp; 2 2015, 15:55:22 on x86_64-unknown-linux-gnu<br />&nbsp;&nbsp; </span></div><img src ="http://www.cppblog.com/jinq0123/aggbug/210429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2015-04-23 16:54 <a href="http://www.cppblog.com/jinq0123/archive/2015/04/23/210429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>boost::coroutine 无法显示调用栈</title><link>http://www.cppblog.com/jinq0123/archive/2014/11/07/208808.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 07 Nov 2014 01:45:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/11/07/208808.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/208808.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/11/07/208808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/208808.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/208808.html</trackback:ping><description><![CDATA[<div>boost::coroutine 无法显示调用栈<br /><br />（金庆的专栏）<br /><br />一例因 boost::format() 格式化参数个数错误造成的 coredump,<br />因为使用了 boost::coroutine, 无法显示异常时的调用栈，<br />仅显示了异常的类型：<br /><br /><span style="color: #000080; font-family: Courier;">#0&nbsp; raise()</span><br /><span style="color: #000080; font-family: Courier;">#1&nbsp; abort()</span><br /><span style="color: #000080; font-family: Courier;">#2&nbsp; __gnu_cxx::__verbose_terminate_handler()</span><br /><span style="color: #000080; font-family: Courier;">#3&nbsp; ??</span><br /><span style="color: #000080; font-family: Courier;">#4&nbsp; std::terminate()</span><br /><span style="color: #000080; font-family: Courier;">#5&nbsp; __cxa_throw()</span><br /><span style="color: #000080; font-family: Courier;">#6&nbsp; boost::exception_detail::clone_impl&lt;</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boost::exception_detail::error_info_injector&lt;</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; boost::io::too_many_args&gt; &gt;::rethrow()</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp; at /usr/include/boost/exception/exception.hpp:466</span><br /><span style="color: #000080; font-family: Courier;">#7&nbsp; boost::rethow_exception()</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp; at /usr/include/boost/exception/detail/exception_ptr.hpp:458</span><br /><span style="color: #000080; font-family: Courier;">#8&nbsp; boost::coroutine::detail::coroutine_base_resume&lt;</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void(), boost::coroutines::detail::coroutine_base&lt;void()&gt;, void, 0&gt;</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; ::resume(void)</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp; at /usr/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp:57</span><br /><span style="color: #000080; font-family: Courier;">#9&nbsp; boost::coroutines::detail::coroutine_op&lt;void(), </span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boost::coroutines::coroutine&lt;void(), 0&gt;, void, 0&gt;::operator()(void)</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp; at /usr/include/boost/coroutine/v1/detail/coroutine_op.hpp:46</span><br /><span style="color: #000080; font-family: Courier;">#10 PlayerCoro::operator()</span><br /><span style="color: #000080; font-family: Courier;">&nbsp;&nbsp;&nbsp; at /home/jinqing/mnt/code/server/loginserver/PlayerCoro.h</span><br />&nbsp;&nbsp;&nbsp;</div><img src ="http://www.cppblog.com/jinq0123/aggbug/208808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-11-07 09:45 <a href="http://www.cppblog.com/jinq0123/archive/2014/11/07/208808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>双线服务器策略路由设置</title><link>http://www.cppblog.com/jinq0123/archive/2014/10/24/208667.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 24 Oct 2014 09:05:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/10/24/208667.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/208667.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/10/24/208667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/208667.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/208667.html</trackback:ping><description><![CDATA[<div>双线服务器策略路由设置<br /><p><br /></p><p>（金庆的专栏）</p><p><br /></p>电信网通双线服务器，发现只有电信用户能连，网通不通。<br />经运维检查，发现是策略路由没做好。<br />添加了策略路由后就正常了。<br /><br />双线服务器有2个外网网卡，一个配电信IP, 一个配网通IP.<br />策略路由让电信网的数据走电信网卡，电信网关; 网通的数据走网通的网卡，网通网关。<br /><br />配置方法如下：<br /><br />1. 创建 /etc/rc.d/route.sh<br />需要更改里面的网关地址和服务器地址.<br /><br /><span style="color:#660000;">#!/bin/bash<br />echo '1' &gt; /proc/sys/net/ipv4/ip_forward<br />sed -i -e '/252 dianxin/d' /etc/iproute2/rt_tables<br />sed -i -e '/251 wangtong/d' /etc/iproute2/rt_tables<br />echo '252 dianxin' &gt;&gt; /etc/iproute2/rt_tables<br />echo '251 wangtong' &gt;&gt; /etc/iproute2/rt_tables<br />IF_DIANXIN=eth1<br />IF_WANGTONG=eth2<br />GW_DIANXIN=222.73.123.129<br />GW_WANGTONG=112.65.123.129<br />IP_DIANXIN=222.73.123.45<br />IP_WANGTONG=112.65.123.45<br />ip route flush table dianxin<br />ip route flush table wangtong<br />ip route add default via $GW_DIANXIN dev eth1 table dianxin<br />ip route add default via $GW_WANGTONG dev eth2 table wangtong<br />ip rule add from $IP_DIANXIN table dianxin<br />ip rule add from $IP_WANGTONG table wangtong<br />ip rule add fwmark 1 table dianxin<br />ip rule add fwmark 2 table wangtong<br /></span><br />2. chmod 755 /etc/rc.d/route.sh 赋权<br />3. 执行一次 /etc/rc.d/route.sh<br />4. /etc/rc.d/rc.local文件中加入/etc/rc.d/route.sh, 使之开机启动<br /><br />如果按照这个办法发现端口不通。只有4种可能。<br />1、脚本里面IP写错了。<br />2、服务器本地没有启动端口。<br />3、本地防火墙挡住了。<br />4、交换机端口没有开放。<br /><br />其间因网关填错，脚本执行报错：<br />RTNETLINK answers: no such process<br />网关改正后就没有错了。<br /><br />开通交换机端口和网关地址须询问运营平台的同事。</div><img src ="http://www.cppblog.com/jinq0123/aggbug/208667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-10-24 17:05 <a href="http://www.cppblog.com/jinq0123/archive/2014/10/24/208667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内核自动分配端口号范围</title><link>http://www.cppblog.com/jinq0123/archive/2014/10/07/208507.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Tue, 07 Oct 2014 09:38:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/10/07/208507.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/208507.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/10/07/208507.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/208507.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/208507.html</trackback:ping><description><![CDATA[<div>内核自动分配端口号范围<br /><br />（金庆的专栏）<br /><br />因为单机开多区测试时，因为Tcp连接比较多，很容易出现端口号被占用而无法开启服务进程的情况。<br />例如某个进程连接MySql本地端口号为34567，正好该端口是另一个服务进程的监听端口。<br />本地端口号是内核自动分配的一个空闲端口。<br />内核自动分配端口号范围配置于<br />&nbsp;&nbsp;&nbsp; /proc/sys/net/ipv4/ip_local_port_range<br />它的值应该是32768到61000。<br />所以服务进程的监听端口号应该配成小于32768。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/208507.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-10-07 17:38 <a href="http://www.cppblog.com/jinq0123/archive/2014/10/07/208507.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gcov辅助脚本</title><link>http://www.cppblog.com/jinq0123/archive/2014/09/26/208428.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 26 Sep 2014 13:02:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/09/26/208428.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/208428.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/09/26/208428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/208428.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/208428.html</trackback:ping><description><![CDATA[<div>gcov辅助脚本<br /><br />（金庆的专栏）<br /><br />代码覆盖测试查看结果时，需要进入代码所在目录，调用gcov，然后vi查看。<br /><br />因为代码目录结构复杂，进出子目录太麻烦，所以用以下脚本直接生成与查看。<br /><br />一般是用TSVN列出有更改的文件，将文件列表复制到文本，然后复制其中的CPP文件名作为参数，在代码根目录下执行脚本。<br /><br /><span style="color: #800000; font-family: Courier;">#!/bin/sh</span><br /><span style="color: #800000; font-family: Courier;"># gcov.sh</span><br /><span style="color: #800000; font-family: Courier;"># Usage: gcov.sh abc.sh</span><br /><span style="color: #800000; font-family: Courier;"># Find file and cd to it, then call gcov and vim the result.</span><br /><br /><span style="color: #800000; font-family: Courier;">if [ $# -eq 0 ]</span><br /><span style="color: #800000; font-family: Courier;">then</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp;&nbsp; echo Usage: $0 SOURCE_FILE</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp; &nbsp;echo Example: $0 abc.cpp</span><br /><span style="color: #800000; font-family: Courier;">&nbsp;&nbsp; &nbsp;exit</span><br /><span style="color: #800000; font-family: Courier;">fi</span><br /><br /><span style="color: #800000; font-family: Courier;">DIR=`find . -name $1.gcda -exec dirname {} \;`</span><br /><span style="color: #800000; font-family: Courier;">cd ${DIR}</span><br /><span style="color: #800000; font-family: Courier;">gcov $1.gcda</span><br /><span style="color: #800000; font-family: Courier;">vim +/##### $1.gcov</span><br /><br />说明：<br />find 在当前目录下查找文件。<br />dirname 在查找结果中获取目录名<br />cd 进入目录<br />gcov 在该目录下执行 gcov<br />vim 打开gcov输出文件，参数 +/##### 用于查找 ##### 并跳到该行。<br />&nbsp;&nbsp;&nbsp; ##### 是源代码未执行的标记。<br />&nbsp;&nbsp; &nbsp;<br />该脚本不能处理多个文件具有相同文件名的情况。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/208428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-09-26 21:02 <a href="http://www.cppblog.com/jinq0123/archive/2014/09/26/208428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>shell脚本整段注释</title><link>http://www.cppblog.com/jinq0123/archive/2014/04/01/206413.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Tue, 01 Apr 2014 01:55:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/04/01/206413.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/206413.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/04/01/206413.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/206413.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/206413.html</trackback:ping><description><![CDATA[<div>摘自：http://zhidao.baidu.com/link?url=XmCCZmfluRe6n8TjPRKJTx4GGOUPSGX1VNBm-euqGdpKGpveTESxC0HL90UBNT5nZCvmvfq2oIJdP3JO5EoPSq<br /><br />利用shell空语句注释整段代码<br /><br />: &lt;&lt; COMMENTBLOCK<br />&nbsp;&nbsp; shell脚本代码段<br />COMMENTBLOCK<br />这个用来注释整段脚本代码。 : 是shell中的空语句。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/206413.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-04-01 09:55 <a href="http://www.cppblog.com/jinq0123/archive/2014/04/01/206413.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gcov 统计 inline 函数</title><link>http://www.cppblog.com/jinq0123/archive/2014/02/28/205983.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 28 Feb 2014 04:36:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/02/28/205983.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/205983.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/02/28/205983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/205983.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/205983.html</trackback:ping><description><![CDATA[<div><p>gcov 统计 inline 函数<br /></p><p>（金庆的专栏）</p><p><br /></p><p>gcov可以统计 inline&nbsp; 函数，可是实际使用中碰到统计次数总是为0的现象。</p><p><br /></p><p>假设类A的头文件为 A.h, 实现文件为 A.cpp.</p><p>A 有几个 inline&nbsp; 成员函数定义在 A.h 中。</p><p>使用 gcov&nbsp; 统计 A 的代码覆盖率时，可能会发现 A.h 中的 inline 成员调用次数为空或0。</p><p>除了确实未调用的原因，可能是 gcov 统计的对象错了。</p><p>"gcov A.cpp" 统计的是 A.cpp 中实现的函数代码，如果 A.cpp&nbsp; 中未调用自身的 inline&nbsp; 函数，统计结果确实为0。</p><p>只有到这些 inline 的调用方 cpp 文件中去统计，才会有想要的结果。</p><p>例如，B.cpp 中调用了 A 的 inline&nbsp; 函数，"gcov B.cpp" 才会统计出这些 inline 代码.</p><p>参考：</p><h2><a target="_blank" id="viewpost1_TitleUrl" href="http://www.cppblog.com/codejie/archive/2012/09/21/191508.html">Why the inline function can not be covered?</a></h2><p><br /></p><p>另外，CMake&nbsp; 构建的.o文件命名不是 A.o,&nbsp; 而是 A.cpp.o,&nbsp; 所以</p><p>gcov A.cpp</p><p>会报 A.gcno 不存在。</p><p>实际文件应该是 A.cpp.gcno.</p><p>&nbsp;把它复制为 A.gcno 就行了。</p><p>或者用 <br /></p><p>gcov A.cpp.gcda</p><p>不知为什么，可以直接用 gcda 文件作为输入。</p><p>或者</p><p>gcov -o A.cpp.o A.cpp</p><p>这样应该是标准的调用方式。</p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/205983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-02-28 12:36 <a href="http://www.cppblog.com/jinq0123/archive/2014/02/28/205983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux编译Windows共享目录下代码</title><link>http://www.cppblog.com/jinq0123/archive/2014/02/26/205948.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 26 Feb 2014 03:47:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2014/02/26/205948.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/205948.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2014/02/26/205948.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/205948.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/205948.html</trackback:ping><description><![CDATA[<div>Linux编译Windows共享目录下代码<br /><br />（金庆的专栏）<br /><br />万神服务器代码是跨平台的。平时策划在Windows上开自己的服务器测试，测试和发布服务器为Linux.<br />开发时，先在Windows上编译测试，再到Linux上编译测试。<br />因为用VC开发，可以使用VAssist, MetalScroll工具辅助，开发效率高。<br /><br />VC编译通过，gcc编译仍会有出错。<br />用CMake构建时，编译目录与源码目录是分开的，这样就可以在 Linux 上编译 Windows 共享目录下的代码。<br />工作目录在Windows上，Linux下编译时，可以读取Windows下共享的工作目录源码。<br />编译时只需读取共享目录下的源码文件，不需要写共享目录，所以编译速度不会下降太多。<br /><br />假设Windows下的工作目录为 d:\Game, 共享为 \\192.168.1.2\Game.<br />在 Linux 上 mount 该共享目录：<br />&nbsp; mount //192.168.1.2/Game ~/Game -o user=jinqing<br /><br />假设 Linux 上编译目录为 ~/build/debug/, 在该目录下运行 cmake<br /><span style="color: #000080;">&nbsp; cmake ~/Game/code -DCMAKE_BUILD_TYPE=Debug</span><br />然后<br /><span style="color: #000080;">&nbsp; make</span><br />&nbsp; <br />Win7上共享到 Linux 比较麻烦， 因为默认不开管理共享，需要开几个设置，并修改注册表。<br />可参考：Linux连接至Win7共享文件夹 ( http://www.examw.com/linux/all/158013/ )<br /><br />需要将2个系统的时间校对下，不然可能不能触发make, 或者时钟警告。<br /><br />因为Windows下文件名不区分大小写，所以 #include 文件名中大小写错误无法检测。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/205948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2014-02-26 11:47 <a href="http://www.cppblog.com/jinq0123/archive/2014/02/26/205948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4xx/log4j异步日志配置示例</title><link>http://www.cppblog.com/jinq0123/archive/2013/12/04/204580.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 04 Dec 2013 04:05:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2013/12/04/204580.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/204580.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2013/12/04/204580.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/204580.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/204580.html</trackback:ping><description><![CDATA[<br />
<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><span style="color: #0000ff;">&lt;?</span><span style="color: #FF00FF; ">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"&nbsp;</span><span style="color: #0000FF; ">?&gt;</span><span style="color: #000000; "><br />
</span><span style="color: #0000FF; ">&lt;!</span><span style="color: #FF00FF; ">DOCTYPE&nbsp;log4j:configuration&nbsp;SYSTEM&nbsp;"log4j.dtd"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">log4j:configuration&nbsp;</span><span style="color: #FF0000; ">xmlns:log4j</span><span style="color: #0000FF; ">='http://jakarta.apache.org/log4j/'&nbsp;</span><span style="color: #FF0000; ">debug</span><span style="color: #0000FF; ">="false"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp; </span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ROLLING"</span><span style="color: #FF0000; ">&nbsp;class</span><span style="color: #0000FF; ">="org.apache.log4j.RollingFileAppender"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">layout&nbsp;</span><span style="color: #FF0000; ">class</span><span style="color: #0000FF; ">="org.apache.log4j.PatternLayout"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ConversionPattern"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="%d&nbsp;%5p&nbsp;%c&nbsp;%x&nbsp;-&nbsp;%m%n"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">layout</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="File"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="/var/log/4j/log_gsX.log"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="MaxFileSize"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="50MB"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="MaxBackupIndex"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="9"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">appender</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="DAILY_LUA"</span><span style="color: #FF0000; ">&nbsp;class</span><span style="color: #0000FF; ">="org.apache.log4j.DailyRollingFileAppender"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">layout&nbsp;</span><span style="color: #FF0000; ">class</span><span style="color: #0000FF; ">="org.apache.log4j.PatternLayout"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ConversionPattern"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="%d&nbsp;%5p&nbsp;%c&nbsp;%x&nbsp;-&nbsp;%m%n"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">layout</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="File"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="/var/log/4j/log_gsX_lua.log"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="DatePattern"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="'.'yyyy-MM-dd"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">appender</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="CONSOLE"</span><span style="color: #FF0000; ">&nbsp;class</span><span style="color: #0000FF; ">="org.apache.log4j.ConsoleAppender"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">layout&nbsp;</span><span style="color: #FF0000; ">class</span><span style="color: #0000FF; ">="org.apache.log4j.PatternLayout"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ConversionPattern"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="%d&nbsp;%5p&nbsp;%c&nbsp;%x&nbsp;-&nbsp;%m%n"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">layout</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="Threshold"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="info"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">appender</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ASYNC"</span><span style="color: #FF0000; ">&nbsp;class</span><span style="color: #0000FF; ">="org.apache.log4j.AsyncAppender"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="BufferSize"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="100000"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="Blocking"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="false"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender-ref&nbsp;</span><span style="color: #FF0000; ">ref</span><span style="color: #0000FF; ">="ROLLING"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender-ref&nbsp;</span><span style="color: #FF0000; ">ref</span><span style="color: #0000FF; ">="CONSOLE"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">appender</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="ASYNC_LUA"</span><span style="color: #FF0000; ">&nbsp;class</span><span style="color: #0000FF; ">="org.apache.log4j.AsyncAppender"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="BufferSize"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="100000"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">param&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="Blocking"</span><span style="color: #FF0000; ">&nbsp;value</span><span style="color: #0000FF; ">="false"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender-ref&nbsp;</span><span style="color: #FF0000; ">ref</span><span style="color: #0000FF; ">="DAILY_LUA"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">appender</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">root</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">level&nbsp;</span><span style="color: #FF0000; ">value</span><span style="color: #0000FF; ">="info"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender-ref&nbsp;</span><span style="color: #FF0000; ">ref</span><span style="color: #0000FF; ">="ASYNC"</span><span style="color: #FF0000; ">&nbsp;</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">root</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">logger&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="Lua"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">level&nbsp;</span><span style="color: #FF0000; ">value</span><span style="color: #0000FF; ">="info"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; ">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">appender-ref&nbsp;</span><span style="color: #FF0000; ">ref</span><span style="color: #0000FF; ">="ASYNC_LUA"</span><span style="color: #FF0000; ">&nbsp;</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">logger</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">logger&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="main"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">level&nbsp;</span><span style="color: #FF0000; ">value</span><span style="color: #0000FF; ">="info"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; ">&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">logger</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">logger&nbsp;</span><span style="color: #FF0000; ">name</span><span style="color: #0000FF; ">="THSever"</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">level&nbsp;</span><span style="color: #FF0000; ">value</span><span style="color: #0000FF; ">="debug"</span><span style="color: #0000FF; ">/&gt;</span><span style="color: #000000; ">&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">logger</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000; "><br />
</span><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">log4j:configuration</span><span style="color: #0000FF; ">&gt;</span><span style="color: #000000;"><br />
<br />
</span></div>
<div><p>ASYNC异步输出到ROLLING和CONSOLE。</p><p>另外，Lua日志异步输出为每天一个的独立日志。</p><p>默认仅输出INFO日志，THServer日志类输出DEBUG日志。</p><p>CONSOLE屏蔽DEBUG日志。</p>每个服务器使用相类似的配置，仅输出文件名不同。可用如下Shell脚本生成各个配置文件：<br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">for</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #0000FF; ">in</span><span style="color: #000000; ">&nbsp;{</span><span style="color: #000000; ">2</span><span style="color: #000000; ">..</span><span style="color: #000000; ">32</span><span style="color: #000000; ">}<br />do<br />&nbsp;&nbsp;sed&nbsp;</span><span style="color: #800000; ">'</span><span style="color: #800000; ">s/gsX/gs</span><span style="color: #800000; ">'</span><span style="color: #000000; ">${i}</span><span style="color: #800000; ">'</span><span style="color: #800000; ">/g</span><span style="color: #800000; ">'</span><span style="color: #000000; ">&nbsp;log4j_gsX.xml&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000;">&nbsp;log4j_gs${i}.xml<br />done</span></div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/204580.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2013-12-04 12:05 <a href="http://www.cppblog.com/jinq0123/archive/2013/12/04/204580.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于C++程序的编码问题</title><link>http://www.cppblog.com/jinq0123/archive/2013/11/29/204516.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 29 Nov 2013 09:08:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2013/11/29/204516.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/204516.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2013/11/29/204516.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/204516.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/204516.html</trackback:ping><description><![CDATA[<div>转自： <a href="http://blog.chinaunix.net/uid-26790551-id-3190813.html">http://blog.chinaunix.net/uid-26790551-id-3190813.html</a><br /><br />
<div style="word-wrap: break-word" class="Blog_wz1">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">我们传统的程序基本都只在Windows或只在Linux下运行，Windows程序使用简体<br />中文GB18030编码，Linux程序则只使用英文，多年以来这些程序运行起来都没有<br />问题。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">近年来，随着程序的组件化，部分代码特别是公用组件都需要同时支持Windows<br />及Linux平台，这样就出现了不同程度的编码问题，例如在编译时编译器报错，<br />或者在运行时出现乱码。这些问题都和程序选用的字符编码不正确有关。</font></p></div>
<p><span id="more-132"><font color="#800080" size="4" face="楷体_GB2312"></font></span></p>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">本文简要地分析了C++的一些字符编码问题，并提供了建议的方案。受经验和时<br />间的限制，有些内容可能不一定全面，仅供大家参考。</font></p></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">1. C++源文件的编码需要特别考虑吗？</font> 
<div class="sectionbody">
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>1.1. 几个相关概念</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">首先要区分几个概念：</font></p></div>
<div class="dlist"><font color="#800080" size="4" face="楷体_GB2312">C++源文件的编码 </font>
<p><font color="#800080" size="4" face="楷体_GB2312">指的是C++源程序文件（.cpp/.h）本身使用什么字符编码（GB18030/UTF-8等）。 </font></p><font color="#800080" size="4" face="楷体_GB2312">C++程序的内码 </font>
<p><font color="#800080" size="4" face="楷体_GB2312">编译后，C++中的字符串常量都会变成一串字节存放在可执行文件中。这个内<br />码指的就是在可执行文件中，字符串以什么编码进行存放。这里的字符串常量<br />指的是窄字符（char）而非宽字符（wchar_t）。宽字符通常是以Unicode（VC<br />使用UTF-16BE，gcc使用UTF-32BE）存放。 </font></p><font color="#800080" size="4" face="楷体_GB2312">运行环境编码 </font>
<p><font color="#800080" size="4" face="楷体_GB2312">指的是执行程序时，操作系统或终端所使用的编码。程序中输出的字符最终要<br />转换为运行环境编码才能正确显示，否则就会出现乱码。 </font></p></div></div>
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>1.2. 各种环境下通常使用的编码</strong></font> 
<div class="paragraph">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">C++源文件的编码</font></div>
<p><font color="#800080" size="4" face="楷体_GB2312">通常在简体中文Windows环境下，各种编辑器（包括Visual Studio）新建文件的<br />缺省编码都是GB18030，所以不特别指定的话，Windows环境下C++源文件的编码<br />通常为GB18030。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">而在Linux环境下，最常使用，也是推荐使用的是UTF-8编码。</font></p></div>
<div class="paragraph">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">C++程序的内码</font></div>
<p><font color="#800080" size="4" face="楷体_GB2312">一般来说，我们常用的简体中文版VC所使用的内码是GB18030，而gcc/g++使用的<br />内码缺省是utf-8，但可以通过-fexec-charset参数进行修改。</font></p></div>
<div class="admonitionblock">
<table>
<tbody>
<tr>
<td class="icon">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">Note</font></div></td>
<td class="content"><font color="#800080" size="4" face="楷体_GB2312">可以通过在程序中打印字符串每个字节十六进制形式来判断程序所使用的内码。</font></td></tr></tbody></table></div>
<div class="paragraph">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">运行环境编码</font></div>
<p><font color="#800080" size="4" face="楷体_GB2312">我们常用的简体中文版Windows的环境编码是GB18030，而Linux下最常用的环境<br />编码是UTF-8。</font></p></div></div>
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>1.3. 这几个编码之间的关系</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">源程序需要由编译器编译为目标文件，目标文件运行后输出信息到终端，因此这<br />几个编码之间存在一些的关联：</font></p></div>
<div class="listingblock">
<div class="content"><font color="#800080" size="4" face="楷体_GB2312">+--------+ | 源程序 |----------源文件编码 +---+----+ | 编译器编译 +---+----+ |目标文件|----------程序内码 +---+----+ | 运行后输出信息 +---+----+ | 输出 |----------运行环境编码 +--------+</font></div></div>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">编译器需要正确识别源文件的编码，把源文件编译为目标文件，并把源文件中<br />的以源文件编码的字符串转换为以程序内码编制的字符串保存在目标文件中。 </font></p>
<div class="admonitionblock">
<table>
<tbody>
<tr>
<td class="icon">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">Note</font></div></td>
<td class="content"><font color="#800080" size="4" face="楷体_GB2312">当源文件的字符编码与程序内码都是UTF-8时（gcc的缺省情况），gcc似乎并不会对源文件中的字符编码进行转换，而是直接把字符串原样存放到目标文<br />件中，在这种情况下，源程序中的GB18030编码的字符串在输出时仍然为GB18030<br />编码。但如果在其它源文件字符编码的实际值与编译选项不同时，会在编译时报无法从XXX转换到UTF-8的错，因此还不清楚为什么两个编码都是UTF-8时，GB18030 编码的源文件能通过编译。</font></td></tr></tbody></table></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">C++标准库需要正确识别终端的运行环境编码，并把程序的输出转换为运行环<br />境所使用的编码，以便正确显示。 </font></p></li></ul></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">在这过程中，如果有一个环节出现问题，就会导致程序的输出发生异常，产生乱<br />码或其它更严重的后果。</font></p></div></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">2. 源文件应该采用什么编码？</font> 
<div class="sectionbody">
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>2.1. 编译器对不同源文件编码的支持一样吗？</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">根据 </font><a href="http://stackoverflow.com/questions/688760/how-to-create-a-utf-8-string-literal-in-visual-c-2008" target="_blank"><font color="#800080" size="4" face="楷体_GB2312">http://stackoverflow.com/questions/688760/how-to-create-a-utf-8-string-literal-in-visual-c-2008</font></a><br /><font color="#800080" size="4" face="楷体_GB2312">一文中提供的资料，gcc/vc各版本对C++源文件编码有不同的处理：</font></p></div>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">gcc (v4.3.2 20081105): </font></p>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">支持UTF-8编码的源文件，UTF-8编码的源文件<strong>不能</strong>有BOM。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">根据 </font><a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33415" target="_blank"><font color="#800080" size="4" face="楷体_GB2312">http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33415</font></a><font color="#800080" size="4" face="楷体_GB2312"> ，似乎gcc 4.4.0<br />开始支持带BOM的UTF-8文件。</font></p></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">vc2003: </font></p></li></ul></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">支持UTF-8编码的源文件，UTF-8编码的源文件可以有BOM，也可以没有。</font></p></div>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">vc2005+: </font></p></li></ul></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">如果源文件使用UTF-8编码的话，<strong>必须有</strong>BOM。</font></p></div>
<div class="admonitionblock">
<table>
<tbody>
<tr>
<td class="icon">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">Note</font></div></td>
<td class="content"><font color="#800080" size="4" face="楷体_GB2312">gcc提供了-finput-charset参数可以指定源文件的字符编码，但由于标准<br />头文件都是ascii编码的，因此如果要引用标准头文件的话，源代码的编码必须兼容ascii。而vc未能找到类似的选项。</font></td></tr></tbody></table></div></div>
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>2.2. 源文件应该采用什么编码？</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">很多文章都推荐C/C++代码中只使用ascii字符，如果有非ascii字符可以用\xHH<br />或\uXXXX表示。注释中建议使用utf-8编码。也可以使用</font><a href="http://www.gnu.org/software/gettext/" target="_blank"><font color="#800080" size="4" face="楷体_GB2312">gettext</font></a><font color="#800080" size="4" face="楷体_GB2312"> 把非ascii字符串放到单独的语言文件中，而在源代码中只保留ascii字符。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">在实践中，由于\xHH或\uXXXX等方式很不直观，容易出错且不易发现，而未必所<br />有程序都需要支持多语言，因此未必想引入gettext或类似的解决方案。在这样<br />的情况下，大家都习惯在源程序文件中直接写入中文等非ascii字符，这就需要<br />选择一种至少能被gcc和vc接受的文件编码。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">本来，Unicode是解决多语言问题的最好选择，而UTF-8由于与ASCII兼容，也是<br />最通用的Unicode编码方式，但从上面的资料中可见，如果用UTF-8的话，gcc（<br />至少是低版本）不允许有BOM，而vc2005 以上要求必须有BOM，因此同一个文件<br />无法在gcc及vc下通过编译，UTF-8似乎不是一个好的选择。但如果使用gcc比较<br />高的版本（4.4.0以上？），使用带BOM的UTF-8编码文件应该也是可行的。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">考虑到目前现状，我们一般都在简体中文Windows下工作，源文件中使用GB18030<br />编码似乎是一个比较现实的选择。在vc下可以直接编译，而在gcc下也可以通过<br />增加编译选项-finput-charset=gb18030予以支持。而且根据维基百科中GB18030<br />的词条内容，GB18030 is a superset of ASCII and can represent the whole<br />range of Unicode code points（GB18030向后兼容ASCII，并且能表示所有的<br />Unicode码点），因此使用GB18030有足够的表达能力，可以表示所有的Unicode<br />字符。使用GB18030的唯一缺点就是在非简体中文版本的VC下，由于无法指定源<br />文件的编码，因此有可能无法正确识别此编码的源文件。</font></p></div></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">3. 应该使用什么程序内码？</font> 
<div class="sectionbody">
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">正如前面提到的，C++有窄字符（char）和宽字符（wchar_t）的分别，分别有一<br />套相应的类和函数（string/cout/strlen与wstring/wcout/wcslen等）。前者在<br />不同的编译器下有不同的缺省编码（简体中文vc是GB18030，gcc是UTF-8），后<br />者一般都使用Unicode，其中vc下使用UTF-16，gcc缺省使用UTF-32。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">C++在输出窄字符时会按程序内码原样输出，不会进行编码转换，因此在使用窄<br />字符时要求程序内码与运行环境编码一致，这样才不会出现乱码。由于简体中文<br />版vc的程序内码是GB18030，因此使用窄字符的vc程序只能运行在GB18030环境下<br />。同样，由于gcc缺省使用UTF-8作为程序内码，因此使用窄字符的gcc程序只能<br />运行在UTF-8的终端环境下。（这里说的都是在源代码中直接写中文等非ascii字<br />符的程序。用前面提到的gettext及其它工具，使用窄字符的程序也可以在不同<br />编码的运行环境中正确输出中文）</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">C++在输出宽字符时会自动转换为运行环境的编码，因此只要正确设置了运行环<br />境编码，同一个程序就可以在不同编码的运行环境中正确显示中文。这一点与<br />Java/.Net很象，Java/.Net的字符串类型都使用Unicode，在输入/输出时都需要<br />与当前运行环境的编码进行互转。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">一般来说，如果需要支持多语言，有两种比较好的做法：</font></p></div>
<div class="olist arabic">
<ol class="arabic"><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，但源程序中只使用ascii字符，非ascii字符通过gettext或其它<br />工具放到单独的文件中，由gettext等工具处理编码转换的问题。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">在各种编码的运行环境中均能正确输出中文。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">程序中不能直接出现非ascii字符，也不能通过\uXXXX方式指定非ascii字符，后者也会被编译器转换为非ascii字符并存放在目标文件中。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">注释中可以使用ascii兼容的编码，不影响编译器。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">有比较多的现成代码可供重用。 </font></p></li></ul></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用宽字符。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">在各种编码的运行环境中均能正确输出中文。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">程序中可以使用非ascii字符。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">需要配合前面的源程序文件编码设置，让编译器能正确识别源程序中的非<br />ascii字符。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">由于以前使用宽字符的程序比较少，可供重用的代码较少。 </font></p></li></ul></div></li></ol></div>
<div class="admonitionblock">
<table>
<tbody>
<tr>
<td class="icon">
<div class="title"><font color="#800080" size="4" face="楷体_GB2312">Note</font></div></td>
<td class="content"><font color="#800080" size="4" face="楷体_GB2312">如果程序中需要一些固定字符编码的字符串常量，例如固定是GB18030<br />编码的字符串常量，这些常量应该以\xXX的方式存放字符串常量经GB18030编码后的内容，这样的内容才不会被转换为程序的内码，也不会转换为运行环境编码。</font></td></tr></tbody></table></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">4. 运行环境应该用什么字符编码？</font> 
<div class="sectionbody">
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">正如上面提到的，使用窄字符和使用宽字符的程序对运行环境的字符编码要求是<br />不一样的。</font></p></div>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用宽字符，只要在程序中正确设置当前环境的字符编码（一般通过locale::global(locale("")) 进行设置），C++标准库会在输入、输出时正<br />确进行字符编码转换，因此可以适应各种编码的运行环境。</font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，但程序中不出现非ascii字符的话，对运行环境没有特别要求，<br />可以适应各种编码的运行环境。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，程序中也直接使用汉字等非ascii字符的话，由于C++标准库会把<br />目标文件中保存的字符串（以程序内码保存）直接输出，不会进行字符编码转换，因此要求运行环境的编码与程序内码一致。即简体中文VC编译的程序只能运行在GB18030环境下，gcc编译的程序只能运行在UTF-8环境下（可以在编译时通过-fexec-charset参数进行修改）。 </font></p></li></ul></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">5. C++源文件编码的选择</font> 
<div class="sectionbody">
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>5.1. 几种可行做法</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">根据上面的讨论，目前看来，要兼容Windows/Linux，VC/gcc的话，有几种做法<br />：</font></p></div>
<div class="olist arabic">
<ol class="arabic"><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序中只使用ascii字符，非ascii字符，如中文等通过<br />gettext等工具放到单独的语言包中。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">这种做法比较多人推荐。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容VC及gcc各版本。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">由于源程序中不出现非ascii字符，因此不需要考虑源程序文件的编码问题。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容各种编码的运行环境。 </font></p></li></ul></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序中允许使用非ascii字符。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">要求运行环境的编码与程序内码一致，即只支持GB18030编码的Windows及<br />UTF-8编码的Linux。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">根据源程序使用的编码不同，对编译器的兼容性也不同： </font></p>
<div class="olist loweralpha">
<ol class="loweralpha"><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序使用带BOM的UTF-8编码。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容VC各语种的各版本。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容gcc 4.4.0以上版本。 </font></p></li></ul></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序使用GB18030编码。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容VC的简体中文各版本。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容gcc各版本，但在编译时需要加上-finput-char=gb18030参数。 </font></p></li></ul></div></li></ol></div></li></ul></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用宽字符，源程序中允许使用非ascii字符。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容各种编码的运行环境。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">根据源程序使用的编码不同，对编译器的兼容性也不同： </font></p>
<div class="olist loweralpha">
<ol class="loweralpha"><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序使用带BOM的UTF-8编码。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容VC各语种的各版本。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容gcc 4.4.0以上版本。 </font></p></li></ul></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">使用窄字符，源程序使用GB18030编码。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容VC的简体中文各版本。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">兼容gcc各版本，但在编译时需要加上-finput-char=gb18030参数。 </font></p></li></ul></div></li></ol></div></li></ul></div></li></ol></div></div>
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>5.2. 推荐做法</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">根据我们的现状，对于需要支持多语种的程序，建议使用窄字符，源程序中只使<br />用ascii字符。</font></p></div>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">对于不需要支持多语种的程序，考虑到重用已有的代码，可以考虑使用窄字符，<br />采用GB18030编码，但只能运行在GB18030编码的Windows环境及UTF-8编码的<br />Linux环境下。</font></p></div></div></div></div>
<div class="sect1"><font color="#800080" size="4" face="楷体_GB2312">6. 其它问题</font> 
<div class="sectionbody">
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>6.1. 用户输入、输出及持久化</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">由于用户输入、输出及从文件、网络等设施读写的数据在程序底层看来都是字节<br />流，因此存在在输入时如何把这些字节流解释成有效的信息，在输出时怎么把程<br />序中的信息转换为正确的字节流的问题。</font></p></div>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">如果程序本身不需要处理这些数据，只是把数据从一个来源搬到另一个地方（<br />如把用户输入保存到文件，或者从一个流读入，写到另一个流等），而输入的字符编码与输出的字符编码一致的话，程序不需要对数据进行任何编码转换，只需要把读入的数据按原样写到输出即可，数据的字符编码与程序的编码没有关系。 </font></p>
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">比如网站应用程序，只需要保证用户页面使用UTF-8编码，数据库、数据文件也都使用UTF-8编码，那么用户输入的数据可以直接写入数据库及数据文件，从数据库或数据文件中读取的数据也可以直接展现给用户，不需要进行编码转换。</font></p></div></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">如果程序需要在一定程序上对数据进行处理（如需要判断字符个数、对字符进<br />行比较、在字符串上附加或去掉内容），就要把数据转换为一种明确的字符编码，一般来说是程序内码，再进行处理，在处理后再转换为所需的字符编码进行输出。 </font></p>
<div class="ulist">
<ul><li>
<p><font color="#800080" size="4" face="楷体_GB2312">对于宽字符程序，如果只需要处理采用当前运行环境字符编码的数据，可以通过ios::imbue()可以指定io流的字符编码，在输入、输出时C++标准库会自动在所指定的字符编码与程序内码之间进行编码转换。如果不使用流的话，也可以通过标准的wcstombs()或mbstowcs()函数进行当前编码（通过locale::global()或setlocale()指定）与宽字符之间的转换。</font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">对于窄字符程序，如果数据的字符编码与程序内码一致也不需要进行编码转换，直接处理即可。 </font></p></li><li>
<p><font color="#800080" size="4" face="楷体_GB2312">对于其它情形，需要引入iconv或类似的字符编码转换库，以便实现不同<br />字符编码之间的转换。 </font></p></li></ul></div></li></ul></div></div>
<div class="sect2"><font color="#800080" face="楷体_GB2312"><strong>6.2. gettext、iconv的替代品</strong></font> 
<div class="paragraph">
<p><font color="#800080" size="4" face="楷体_GB2312">由于gettext及iconv都属于GNU Project，考虑到版权因素，并非所有程序，特别是商业程序，都适合使用这些库。在Boost 1.48.0中，Boost.Locale库首次正式发布，该库提供了gettext、iconv的功能，并在此基础上进行了增强，提供了大小写变换、字符顺序比较、时间的处理 、分词、数字的格式化输入/输出、消息格式化、多语种支持、字符编码转换等功能，值得进一步研究及使用。</font></p></div></div></div></div></div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/204516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2013-11-29 17:08 <a href="http://www.cppblog.com/jinq0123/archive/2013/11/29/204516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CMake添加-D_DEBUG宏 </title><link>http://www.cppblog.com/jinq0123/archive/2013/07/26/202141.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 26 Jul 2013 08:33:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2013/07/26/202141.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/202141.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2013/07/26/202141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/202141.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/202141.html</trackback:ping><description><![CDATA[<div><div id="article_content"> <p>Linux下Debug版不会自动添加 _DEBUG宏，只有NDEBUG宏可用。</p><p><br /></p><p>cmake ../src _DCMAKE_BUILD_TYPE=Debug -D_DEBUG</p><p>会报错： -D_DEBUG should be: VAR:type=value</p><p>需要-D_DEBUG=1.</p><p><br /></p><p>改为在CMakeLists.txt中添加：</p><p>if (CMAKE_BUILD_TYPE STREQUAL Debug)</p><p>&nbsp;&nbsp;&nbsp; add_definitions(</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -D_DEBUG<br /></p><p>&nbsp;&nbsp;&nbsp; )<br /></p><p>endif ()</p><p><br /></p> </div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/202141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2013-07-26 16:33 <a href="http://www.cppblog.com/jinq0123/archive/2013/07/26/202141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Win7访问Redhat samba共享</title><link>http://www.cppblog.com/jinq0123/archive/2012/09/17/190955.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Mon, 17 Sep 2012 03:37:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/09/17/190955.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/190955.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/09/17/190955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/190955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/190955.html</trackback:ping><description><![CDATA[<div><p>Win7访问Redhat samba共享</p><p>首先是开启samba:</p><p>service smb start</p><p>service smb restart</p><p>samba的配置文件是/ect/samba/smb.conf, 几乎不用改，使用默认配置就行了。</p><p>默认是使用 security=user 模式共享，需要输入用户名密码才能访问。</p><p>默认有[homes]共享配置，各个用户可访问自己的主目录。</p><p>如添加新用户：</p><p>useradd jinqing</p><p>passwd jinqing</p><p>smbpasswd -a jinqing</p><p>smb需要自己的用户密码，需用smbpasswd设置。</p><p>这样就共享了/home/jinqing.</p><p>测试：smbclient //localhost/jinqing -Ujinqing</p><p>需要设置Selinux参数，以允许共享访问，可参照smb.conf中的注释运行：</p><p>setsebool -P samba_enable_home_dirs on</p><p><br /></p><p>然后是win7需要设置安全策略，不然也会连不上。<br /></p><p>打开管理工具，&#8220;本地策略&#8221;-&gt;&#8220;安全选项&#8221;-&gt;&#8220;网络安全：LAN Manager 身份验证级别&#8221;；<br />单击列表中：发送LM和NTLMv2，如果已协商，则使用NTLMv2协议。<br /></p><p><br /></p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/190955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-09-17 11:37 <a href="http://www.cppblog.com/jinq0123/archive/2012/09/17/190955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CMake生成版本号</title><link>http://www.cppblog.com/jinq0123/archive/2012/08/15/187268.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 15 Aug 2012 04:30:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/08/15/187268.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/187268.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/08/15/187268.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/187268.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/187268.html</trackback:ping><description><![CDATA[<div>CMake生成版本号<br /><br />（金庆的专栏）<br /><br />原来的CMake需要用shell脚本生成SVN版本号，再作为cmake参数传入。<br /><br />CMake调用脚本示例：<br /><br /><span style="font-family:Courier New;color:#660000;">#!/bin/sh<br /># cmake.sh<br /><br />ServerCodeRoot=~/Code/Server<br />CodeRevNum=`svn info ${ServerCodeRoot} | grep Revision | awk -F' ' '{ print $2 }'`<br />cmake S{ServerCodeRoot} -DCMAKE_BUILD_TYPE=Release -DVERSION_REVISION=S{CodeRevNum}<br /></span><br />CMakeLists.txt中如下配置：<br /><span style="font-family:Courier New;color:#660000;">configure_file(<br />&nbsp; "Version.h.in"<br />&nbsp; "Version.h"<br />)</span><br /><br />Version.h.in如下：<br /><br /><span style="font-family:Courier New;color:#660000;">#include &lt;string&gt;<br />const std::string VERSION_MAJOY("1");<br />const std::string VERSION_MINOR("0");<br />const std::string VERSION_REVISION("@VERSION_REVISION@");<br /></span><br />Linux下执行cmake.sh会自动替换SVN版本号。<br /><br />现改为用FIND_PACKAGE(Subversion)方式，不必用shell脚本生成SVN版本号，<br />并且在Windows上也可以生成版本号, cmake调用时不必传VERSION_REVISION参数。<br /><br />CMakeLists.txt改为（参考了开源网游ryzom的CMake）：<br /><br /><span style="font-family:Courier New;color:#660000;">SET(ROOT_DIR ${PROJECT_SOURCE_DIR})<br />IF(EXISTS "${ROOT_DIR}/.svn/")<br />&nbsp; FIND_PACKAGE(Subversion)<br /><br />&nbsp; IF(SUBVERSION_FOUND)<br />&nbsp;&nbsp;&nbsp; Subversion_WC_INFO(${ROOT_DIR} Project)<br />&nbsp;&nbsp;&nbsp; SET(VERSION_REVISION ${Project_WC_REVISION})<br />&nbsp; ENDIF(SUBVERSION_FOUND)<br />ENDIF(EXISTS "${ROOT_DIR}/.svn/")<br /><br />CONFIGURE_FILE(<br />&nbsp; "Version.h.in"<br />&nbsp; "Version.h"<br />)</span><br /><br />如果不是SVN, 而是用Hg, 可用如下脚本：<br /><span style="font-family:Courier New;color:#660000;">IF(EXISTS "${ROOT_DIR}/.hg/")<br />&nbsp; FIND_PACKAGE(Mercurial)<br /><br />&nbsp; IF(MERCURIAL_FOUND)<br />&nbsp;&nbsp;&nbsp; Mercurial_WC_INFO(${ROOT_DIR} ER)<br />&nbsp;&nbsp;&nbsp; SET(REVISION ${ER_WC_REVISION})<br />&nbsp;&nbsp;&nbsp; SET(CHANGESET ${ER_WC_CHANGESET})<br />&nbsp;&nbsp;&nbsp; SET(BRANCH ${ER_WC_BRANCH})<br />&nbsp; ENDIF(MERCURIAL_FOUND)<br />ENDIF(EXISTS "${ROOT_DIR}/.hg/")<br /></span></div><img src ="http://www.cppblog.com/jinq0123/aggbug/187268.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-08-15 12:30 <a href="http://www.cppblog.com/jinq0123/archive/2012/08/15/187268.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多线程开启gprof性能测试的简易方法 </title><link>http://www.cppblog.com/jinq0123/archive/2012/08/01/185908.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 01 Aug 2012 08:23:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/08/01/185908.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/185908.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/08/01/185908.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/185908.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/185908.html</trackback:ping><description><![CDATA[<div><p><div><div>多线程开启gprof性能测试的简易方法</div><br />（金庆的专栏）</div><br /></p><p>用到gprof时才知道，原来gprof只能对主线程统计耗时。manual上也没写线程相关的问题啊？</p><p>不过有现成的解决方案：http://sam.zoy.org/writings/programming/gprof.html</p><p>该方案封装了pthread_create(), 让线程初始化执行一个setitimer(ITIMER_PROF, ...)。</p><p>简易的方法是直接在代码中写个setitimer()。</p><div bg_cpp=""><div><div><strong>[cpp]</strong> <a href="http://blog.csdn.net/jq0123/article/details/7818919#" title="view plain">view plain</a><a href="http://blog.csdn.net/jq0123/article/details/7818919#" title="copy">copy</a></div></div><ol start="1"><li><span>#include&nbsp;&lt;sys/time.h&gt;&nbsp;&nbsp;</span></li><li><span>#include&nbsp;&lt;boost/thread.hpp&gt;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li><span>struct&nbsp;itimerval&nbsp;g_itimer;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li><span>void&nbsp;foo()&nbsp;&nbsp;</span></li><li>{&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;setitimer(ITIMER_PROF,&nbsp;&amp;g_itimer,&nbsp;NULL);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;10000000;&nbsp;i++)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span>void)i;&nbsp;&nbsp;</span></li><li>}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li><span>int&nbsp;main()&nbsp;&nbsp;</span></li><li>{&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;getitimer(ITIMER_PROF,&nbsp;&amp;g_itimer);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;boost::<span>thread&nbsp;t(&amp;foo);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;t.join();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;0;&nbsp;&nbsp;</span></li><li>}&nbsp;&nbsp;</li></ol></div><br />g++ main.cpp -pg -lboost_thread<p>./a.out</p><p>gprof</p><p>这样就能统计出foo()的耗时了。没有setitimer()就不会有foo()的耗时统计。</p><p><br /></p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/185908.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-08-01 16:23 <a href="http://www.cppblog.com/jinq0123/archive/2012/08/01/185908.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySql的CMake选项支持gcov和gprof </title><link>http://www.cppblog.com/jinq0123/archive/2012/07/11/182807.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 11 Jul 2012 04:15:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/07/11/182807.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/182807.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/07/11/182807.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/182807.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/182807.html</trackback:ping><description><![CDATA[<div><p>未来的MySql 5.6.6 中，CMake选项中添加了gprof性能测试支持，见：<br /></p><p>http://dev.mysql.com/doc/refman/5.6/en/source-configuration-options.html</p><p><br /></p><p>ENABLE_GPROF &nbsp;&nbsp; &nbsp;Enable gprof (optimized Linux builds only) &nbsp;&nbsp; &nbsp;OFF &nbsp;&nbsp; &nbsp;5.6.6 &nbsp;&nbsp; &nbsp; <br /></p><p><br /></p><p>代码库中的CMakeLists.txt 摘录如下：</p><div bg_plain=""><ol start="1"><li><span>OPTION(ENABLE_GCOV&nbsp;"Enable&nbsp;gcov&nbsp;(debug,&nbsp;Linux&nbsp;builds&nbsp;only)"&nbsp;OFF)&nbsp;&nbsp;</span></li><li>IF&nbsp;(ENABLE_GCOV&nbsp;AND&nbsp;NOT&nbsp;WIN32&nbsp;AND&nbsp;NOT&nbsp;APPLE)&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_CXX_FLAGS_DEBUG&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_CXX_FLAGS_DEBUG}&nbsp;-fprofile-arcs&nbsp;-ftest-coverage")&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_C_FLAGS_DEBUG&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_C_FLAGS_DEBUG}&nbsp;-fprofile-arcs&nbsp;-ftest-coverage")&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_EXE_LINKER_FLAGS_DEBUG&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_EXE_LINKER_FLAGS_DEBUG}&nbsp;-fprofile-arcs&nbsp;-ftest-coverage&nbsp;-lgcov")&nbsp;&nbsp;</li><li>ENDIF()&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>OPTION(ENABLE_GPROF&nbsp;"Enable&nbsp;gprof&nbsp;(optimized,&nbsp;Linux&nbsp;builds&nbsp;only)"&nbsp;OFF)&nbsp;&nbsp;</li><li>IF&nbsp;(ENABLE_GPROF&nbsp;AND&nbsp;NOT&nbsp;WIN32&nbsp;AND&nbsp;NOT&nbsp;APPLE)&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_C_FLAGS_RELWITHDEBINFO&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_C_FLAGS_RELWITHDEBINFO}&nbsp;-pg")&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_CXX_FLAGS_RELWITHDEBINFO}&nbsp;-pg")&nbsp;&nbsp;</li><li>&nbsp;&nbsp;SET(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;"${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}&nbsp;-pg")&nbsp;&nbsp;</li><li>ENDIF()&nbsp;&nbsp;</li></ol></div></div><img src ="http://www.cppblog.com/jinq0123/aggbug/182807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-07-11 12:15 <a href="http://www.cppblog.com/jinq0123/archive/2012/07/11/182807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CMake添加gcov代码覆盖测试支持 </title><link>http://www.cppblog.com/jinq0123/archive/2012/07/11/182790.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 11 Jul 2012 03:11:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/07/11/182790.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/182790.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/07/11/182790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/182790.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/182790.html</trackback:ping><description><![CDATA[<div><p>CMake添加gcov代码覆盖测试支持</p><p>（金庆的专栏）</p><p>在根CMakeList.txt中添加ENABLE_GCOV选项：<br /></p><p><span style="font-family:Courier New;color:#660000;">OPTION(ENABLE_GCOV "Enable gcov (debug, Linux builds only)" OFF)</span></p><span style="font-family:Courier New;color:#660000;">IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE)<br />&nbsp; SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")<br />&nbsp; SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage")<br />&nbsp; SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage -lgcov")<br />ENDIF()<br /></span><p><br /></p><p>以上代码来自MySQL的CMakeLists.txt.</p><p>如下执行cmake:</p><p>cmake SRC_DIR -DCMAKE_BUILD_TYPE=Debug -DENABLE_GCOV=1</p><p><br /></p><p>编译后就可以看到图文件 *.gcno。</p><p>运行后，可以看到数据文件*.gcda生成。</p>执行 gcov main.cpp.gcno 就生成 main.cpp.gcov 测试结果。</div><img src ="http://www.cppblog.com/jinq0123/aggbug/182790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-07-11 11:11 <a href="http://www.cppblog.com/jinq0123/archive/2012/07/11/182790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CMake区分debug、release版本</title><link>http://www.cppblog.com/jinq0123/archive/2012/03/27/169143.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Tue, 27 Mar 2012 05:56:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/03/27/169143.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/169143.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/03/27/169143.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/169143.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/169143.html</trackback:ping><description><![CDATA[<div><p>摘自： http://www.cppblog.com/tx7do/archive/2010/08/19/124000.html<br /></p><p><br /></p><p>建立debug/release两目录，分别在其中执行cmake -DCMAKE_BUILD_TYPE=Debug（或Release），需要编译不同版本时进入不同目录执行make即可；</p><p><strong>Debug版会使用参数-g；Release版使用-O3 &#8211;DNDEBUG</strong></p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/169143.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-03-27 13:56 <a href="http://www.cppblog.com/jinq0123/archive/2012/03/27/169143.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>建立Socket Policy服务器</title><link>http://www.cppblog.com/jinq0123/archive/2012/01/19/164375.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Thu, 19 Jan 2012 08:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2012/01/19/164375.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/164375.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2012/01/19/164375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/164375.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/164375.html</trackback:ping><description><![CDATA[<div>建立Socket Policy服务器<br /><br />（金庆的专栏）<br /><br />Flash和Unity3D游戏服务器需要开启一个Socket Policy服务器。<br />详细说明见：Setting up a socket policy file server<br />http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html<br /><br />协议如下：<br />Flash或U3D播放器向Socket Policy服务器发送请求：<br />&#8220;&lt;policy-file-request/&gt;\0&#8221;，<br />服务器返回一个xml文本，其中有包含&lt;cross-domain-policy&gt;配置。<br /><br />Adobe提供了Perl和Python代码。Unity3D提供了CSharp代码。<br />cs代码用于Windows. Linux上准备使用Python代码。<br />在以上网页下载：flashpolicyd_v0.6.zip。<br />其中有3个版本：init服务，xinetd服务，独立应用。只需一种即可。<br /><br />按应用的性质，请求量极小，所以最适合应用xinetd.<br />只需运行其中的install.sh就会安装。<br />还需手工在/ect/services中添加服务名flashpolicy和端口843.<br /><br />运行以下指令可以测试一下，输出应该是配置文件的内容。<br />python -c 'print "&lt;policy-file-request/&gt;%c" % 0' | nc 127.0.0.1 843<br /><br />其实以上测试指令在尾部多了个'\n', 不是标准的测试。<br />在in.flashpolicyd.py中多了个strip()去除这个'\n'.<br /><br />实际用U3D测试时，因为没有'\n'结尾，所以in.flashpolicyd.py无法正常工作。<br />需要将35行readline()如下更改：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request = sys.stdin.readline().strip()<br />改为<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; request = sys.stdin.readline(len('&lt;policy-file-request/&gt;\0')).strip()<br />这样就不需要eol就可以读取了。<br /><br />查看其他两个版本的代码没有这个错误，但是有另一个错误，<br />即有可能只读一半的请求造成判断出错。<br /><br />还有一个问题是因为服务是由nobody运行的，环境变量不同，<br />将in.flashpolicyd.py头部的<br />#!/usr/bin/env python<br />明确为<br />#!/usr/local/sbin/python<br />可避免调用低版本的python而报错。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/164375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2012-01-19 16:21 <a href="http://www.cppblog.com/jinq0123/archive/2012/01/19/164375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL无法本地连接</title><link>http://www.cppblog.com/jinq0123/archive/2011/10/21/158831.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 21 Oct 2011 08:27:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2011/10/21/158831.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/158831.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2011/10/21/158831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/158831.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/158831.html</trackback:ping><description><![CDATA[<div>MySQL无法本地连接<br /><br />（金庆的专栏）<br /><br />Linux重启后，发现不知怎么的MySQL无法本地连接。<br /><br />结果phpMyAdmin, Zentao都无法正常工作了。<br /><br />远程的连接用了TCP是正常的，本地连接用了本地socket, 有问题。<br /><br />本地运行mysql客户端会报错：<br />Can&#8217;t connect to local MySQL server through socket &#8216;/var/lib/mysql/mysql.sock&#8217; (2)<br /><br />重启mysql服务也报错：<br /># service mysql restart<br />MySQL server PID file could not be found! <br />Starting MySQL... ...The server quit without updating PID file (/var/lib/mysql/localhost/localdomain.pid)<br /><br />该.pid文件不存在。所以无法关闭mysql. 正在运行的mysql服务一直无法关闭。<br /><br />参考：http://zhujipi.com/vps/109.html<br />说明，Mysql的进程卡死了，这时用就要把这些卡死的进程都关闭。<br /><br />mysql服务重启成功后恢复正常。<br /></div><img src ="http://www.cppblog.com/jinq0123/aggbug/158831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2011-10-21 16:27 <a href="http://www.cppblog.com/jinq0123/archive/2011/10/21/158831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设定“svn:needs-lock”属性</title><link>http://www.cppblog.com/jinq0123/archive/2011/10/12/158128.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 12 Oct 2011 06:33:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2011/10/12/158128.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/158128.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2011/10/12/158128.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/158128.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/158128.html</trackback:ping><description><![CDATA[<div><p>摘自： http://www.cnblogs.com/LittleFox/archive/2009/04/08/1431781.html</p><p><br /></p><p><span id="comment_body_1498206">设定&#8220;svn:needs-lock&#8221;属性<br />使用命令行锁定&#8220;介绍.doc&#8221;：<br /><br />svn propset svn:needs-lock 'x' 介绍.doc<br /><br />运 行这个命令后，&#8220;介绍.doc&#8221;就已经是设置了&#8220;svn:needs-lock &#8221;，但为了使之生效还要运行&#8220;svn  commit&#8221;，之后其他用户update的时候就会发现这个文件已经是只读的了。需要注意的是我们设置的属性值是&#8220;x&#8221;，实际上任意值都可以，  Subversion会忽略其内容。<br /><br />使用TortoiseSVN设定属性也很简单：<br /><br />&#8220;介绍.doc&#8221;右键选中-  &gt;属性-&gt;Subversion选项夹-&gt;properties-&gt;add，然后在弹出的窗口中的property  name选择&#8220;svn:needs-lock&#8221;，值任意，然后选择OK。之后再提交&#8220;介绍.doc&#8221;即可。</span><br /></p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/158128.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2011-10-12 14:33 <a href="http://www.cppblog.com/jinq0123/archive/2011/10/12/158128.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决 undefined symbol: php_ini_scanned_files</title><link>http://www.cppblog.com/jinq0123/archive/2011/09/26/156861.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Mon, 26 Sep 2011 08:25:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2011/09/26/156861.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/156861.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2011/09/26/156861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/156861.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/156861.html</trackback:ping><description><![CDATA[<div>apache加载php时出错：<br />Starting httpd: httpd: Syntax error on line 57  of /usr/local/apache2/conf/httpd.conf: Cannot load  /usr/local/apache2/modules/libphp5.so into server:  /usr/local/apache2/modules/libphp5.so: undefined symbol:  php_ini_scanned_files<p>网上搜索的所有方法都没有解决这个错误。</p><p>最后make clean;make;make install就好了。</p><p>估计是需要make clean清除上次的错误才行。</p><p><br /></p></div><img src ="http://www.cppblog.com/jinq0123/aggbug/156861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2011-09-26 16:25 <a href="http://www.cppblog.com/jinq0123/archive/2011/09/26/156861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>预编译输出的行标志</title><link>http://www.cppblog.com/jinq0123/archive/2010/09/15/126636.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 15 Sep 2010 02:53:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2010/09/15/126636.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/126636.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2010/09/15/126636.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/126636.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/126636.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 调用预编译器cpp预编译main.cpp生成main.i文件：<br>    $cpp main.cpp > main.i<br>或者：<br>    $gcc -E main.cpp > main.i<br><br>生成的行号标志中有如下格式的：<br>    # 1 “/usr/include/features.h” 1 3 4&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2010/09/15/126636.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/126636.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2010-09-15 10:53 <a href="http://www.cppblog.com/jinq0123/archive/2010/09/15/126636.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vi查看制表符</title><link>http://www.cppblog.com/jinq0123/archive/2010/05/17/115584.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Mon, 17 May 2010 06:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2010/05/17/115584.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/115584.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2010/05/17/115584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/115584.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/115584.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在VC中编辑->高级菜单中有个“查看空白”，我总是打开的。<br>在VI中，也有类似功能，可以查看TAB及行尾空格。&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2010/05/17/115584.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/115584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2010-05-17 14:21 <a href="http://www.cppblog.com/jinq0123/archive/2010/05/17/115584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cygwin与MinGW的区别</title><link>http://www.cppblog.com/jinq0123/archive/2010/03/29/110795.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Mon, 29 Mar 2010 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2010/03/29/110795.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/110795.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2010/03/29/110795.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/110795.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/110795.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 跟Cygwin相比，最大的区别是其采用的不是 GNU的libc库，而是Windows下的c运行时库mscvrt。&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2010/03/29/110795.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/110795.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2010-03-29 10:25 <a href="http://www.cppblog.com/jinq0123/archive/2010/03/29/110795.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>当心虚函数重载(overloaded-virtual)</title><link>http://www.cppblog.com/jinq0123/archive/2009/05/22/85378.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 22 May 2009 05:59:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2009/05/22/85378.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/85378.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2009/05/22/85378.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/85378.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/85378.html</trackback:ping><description><![CDATA[当心虚函数重载(overloaded-virtual)<br><br>（转载请注明来源于金庆的专栏）<br><br>为网游万王之王3(KOK3)服务器添加新功能的时候, <br>发现某个类成员函数应该是const函数, 因为我的const函数要调用该函数, <br>顺手就加上了const.<br><br>再顺便看到该类有好多个明显是getter函数, 所以都加上了const.<br>编译没错就提交了.<br><br>结果没多久测试就发现了新版本的一个错误, 表现在其他功能上, <br>但由同事纠错后发现是我添加const的后果.<br><br>原来添加const的成员函数中, 有一个是virtual函数, 加了const后与子类的函数原型就不符了.<br>子类的函数成为父类虚函数的一个重载, 使virtual失效, 多态性无法表现出来.<br>解决方法就是子类的相应虚函数中也添加const.<br><br>教训: 更改虚函数原型时, 必须同时更改父类和子类.<br><br>gcc中有个-Woverloaded-virtual警告选项, 会报告这种虚函数重载.<br><br>我在Makefile中打开了-Woverloaded-virtual, 再次编译时就产生了许多警告.<br>大多数警告是正确的函数重载, 但还是发现了一个与我相同的错误, <br>这次是函数参数const有区别, 我发给相关人员处理了.<br><br>因为开了-Werror, 所有警告都会造成编译失败, <br>所以我们不能在Makefile中加入-Woverloaded-virtual警告选项.<br><br>代码示例:<br><br><span style="font-family: courier new; color: #600000;">class A</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">{</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">&nbsp;&nbsp; &nbsp;virtual void f() {};</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">};</span><br style="font-family: courier new; color: #600000;"><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">class B : public A</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">{</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">&nbsp;&nbsp; &nbsp;virtual void f() const {};</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">};</span><br style="font-family: courier new; color: #600000;"><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">int main()</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">{</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">&nbsp;&nbsp; &nbsp;return 0;</span><br style="font-family: courier new; color: #600000;"><span style="font-family: courier new; color: #600000;">}</span><br><br><span style="font-family: courier new; color: #0010ff;">$ g++ main.cpp -Woverloaded-virtual</span><br style="font-family: courier new; color: #0010ff;"><span style="font-family: courier new; color: #0010ff;">main.cpp:3: warning: `virtual void A::f()' was hidden</span><br style="font-family: courier new; color: #0010ff;"><span style="font-family: courier new; color: #0010ff;">main.cpp:8: warning:&nbsp;&nbsp; by `virtual void B::f() const'</span><br><br>Google的代码规范中要求所有子类的虚函数中都加上virtual, 是很有道理的.<br>虽然只要与父类虚函数签名相同, 加不加virtual都是虚函数,<br>但是以后更改函数签名时, 看到virtual很容易知道它是虚函数, 需要父类子类同时更改.<br><br>
<br><img src ="http://www.cppblog.com/jinq0123/aggbug/85378.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2009-05-22 13:59 <a href="http://www.cppblog.com/jinq0123/archive/2009/05/22/85378.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pthread_rwlock使用错误</title><link>http://www.cppblog.com/jinq0123/archive/2008/11/14/pthread_rwlock_abuse.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Fri, 14 Nov 2008 02:47:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2008/11/14/pthread_rwlock_abuse.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/66884.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2008/11/14/pthread_rwlock_abuse.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/66884.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/66884.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 写锁之后读锁竟然没有阻塞, 顺利运行下去了.据常理,写锁之后,试图读加锁时会阻塞.代码如:<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2008/11/14/pthread_rwlock_abuse.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/66884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2008-11-14 10:47 <a href="http://www.cppblog.com/jinq0123/archive/2008/11/14/pthread_rwlock_abuse.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UNIX 技巧</title><link>http://www.cppblog.com/jinq0123/archive/2008/07/30/UnixTricks.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 30 Jul 2008 01:00:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2008/07/30/UnixTricks.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/57488.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2008/07/30/UnixTricks.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/57488.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/57488.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: <br>* 利用位置变量 $0 显示Shell名<br>* bash中输入一半文件名，用TAB键自动补全<br>* ! 历史扩展<br>* 用 pushd 和 popd 在目录树中导航<br>* 查找大于 10MB 的所有文件<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2008/07/30/UnixTricks.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/57488.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2008-07-30 09:00 <a href="http://www.cppblog.com/jinq0123/archive/2008/07/30/UnixTricks.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Unix编程哲学</title><link>http://www.cppblog.com/jinq0123/archive/2007/08/29/UnixPhilosophy.html</link><dc:creator>金庆</dc:creator><author>金庆</author><pubDate>Wed, 29 Aug 2007 07:32:00 GMT</pubDate><guid>http://www.cppblog.com/jinq0123/archive/2007/08/29/UnixPhilosophy.html</guid><wfw:comment>http://www.cppblog.com/jinq0123/comments/31159.html</wfw:comment><comments>http://www.cppblog.com/jinq0123/archive/2007/08/29/UnixPhilosophy.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinq0123/comments/commentRss/31159.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinq0123/services/trackbacks/31159.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Unix编程哲学。参考其它另外三个不同版本的翻译。模块化准则，清晰性准则，组合准则，分离准则，简单性准则，吝啬准则，透明性准则，健壮性准则，表示准则，最小惊奇准则，沉默准则，修复准则，经济性准则，生成准则，优化准则，多样性准则，扩展性准则。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/jinq0123/archive/2007/08/29/UnixPhilosophy.html'>阅读全文</a><img src ="http://www.cppblog.com/jinq0123/aggbug/31159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinq0123/" target="_blank">金庆</a> 2007-08-29 15:32 <a href="http://www.cppblog.com/jinq0123/archive/2007/08/29/UnixPhilosophy.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>