纠错集(持续更新)

来源:互联网 发布:男生180女生160知乎 编辑:程序博客网 时间:2024/05/29 07:13

1.linux下两种常见的压缩包压缩方法:(解包:tar -zxvf  + 包名 需要生成的目录)

bz2文件

time tar -jcvf j.tar.bz2 workspace/

340M 56.8%

real 13m20.975s

user 11m13.872s

sys 0m5.985s


gz文件

time tar -zcvf z.tar.gz workspace/

348M 58.1%

real 2m10.305s

user 0m54.228s

sys 0m7.399s

2.当在一个完整的项目中需要添加一个接口或者一个工具的时候,不一定非要重新定义一个新的类,有的时候这样做会显得更加的累赘,可以在某个已定义的类中添加几个函数就行了,这样会显得更加的清楚和整洁。

3.程序中使用到了一个动态链接库:ldd + 程序名:

        libcurl.so.4 => /usr/lib64/libcurl.so.4 (0x00007ff76c8ad000)
这是一个curl的动态库,支持上传下载,读取网页内容。然后再程序中调用封装好的某个api时出现协议不支持,即https协议,而通过curl -V发现是支持的:

curl 7.14.0 (x86_64-unknown-linux-gnu) libcurl/7.14.0 OpenSSL/1.0.1e zlib/1.2.3 libidn/1.18Protocols: ftp gopher telnet dict ldap http file https ftps Features: IDN IPv6 Largefile NTLM SSL libz 
然后问题就来了,为什么会这样呢?然后就查看了下curl这个程序所链接的库:ldd curl:

        linux-vdso.so.1 =>  (0x00007fff7dfff000)        libcurl.so.3 => /usr/local/lib/libcurl.so.3 (0x00007f8b77c95000)        libidn.so.11 => /lib64/libidn.so.11 (0x00000036a5000000)        libssl.so.1.0.0 => /usr/local/ssl/lib/libssl.so.1.0.0 (0x00007f8b77a2b000)        libcrypto.so.1.0.0 => /usr/local/ssl/lib/libcrypto.so.1.0.0 (0x00007f8b7764f000)        libdl.so.2 => /lib64/libdl.so.2 (0x000000369b800000)        libz.so.1 => /data/mysql/lib/mysql/libz.so.1 (0x00007f8b77438000)        libc.so.6 => /lib64/libc.so.6 (0x000000369b400000)        /lib64/ld-linux-x86-64.so.2 (0x000000369b000000)        libpthread.so.0 => /lib64/libpthread.so.0 (0x000000369bc00000)        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x000000369e000000)        libnsl.so.1 => /lib64/libnsl.so.1 (0x000000369f000000)        libm.so.6 => /lib64/libm.so.6 (0x000000369c000000)        libfreebl3.so => /lib64/libfreebl3.so (0x000000369dc00000)
这里就发现了两个程序所使用的库是不一样的,那么问题就好解决了,直接将curl使用的库
/usr/local/lib/libcurl.so.3 
复制到
/usr/lib64/

然后将该目录下的libcurl.so.4链接到libcurl.so.3,这样就能使用正确的库了,然后ldconfig刷新下缓存。ok。

4.今天不小心在eclipse中把一个项目给删除了,慌了,果断上网百度,得知可以恢复,心情平复了下来。方法如下:

在Eclipse内可以恢复项目内被删除的文件,或者类似SVN那样来具体恢复一个java文件内 被删除的内容。
如果项目内的文件被删除,恢复步骤:
  选中项目,右键;
  选择Restore from Local history;
  在“Check files to restore from local history:”选择对应的要恢复的文件。
需要注意的是,eclipse恢复文件中应该有个类似缓存存在,这样的缓存可能受时间和空间的限制,因此,如果出现删除太大太多的文件,可能就不能恢复了。

这几天受到了不认真的教训,希望能够吃一堑长一智!

5.linux shell中如果执行某个程序需要传递参数,当参数中包含括号时,如:

cp a.text (b).test

直接使用时会报错:

-bash: syntax error near unexpected token `('

这里需要对括号进行转义,有两种方式:

1.在括号两端加上双引号:

cp a.test "(b)".test

2.在括号两队加上斜杠:

cp a.test \(b\).test

6.今天程序core dump了,通过调试发现又是无符号整形取负的问题:

当定义一个uint32_t 类型的变量时,需要特别注意取负的问题,当一个uint32_t类型的变量取负时,会将最高位变为1,然后就会直接变成最大值了,因此经常会造成内存溢出,详见:http://www.cnblogs.com/tenghoo/archive/2008/06/01/1211663.html

下面附一个非常经典的例子:

#include <vector>#include <iostream>using namespace std;int main(){        vector<int> vec(10);        cout << vec.size() << endl;        for(size_t i = vec.size() - 1; i >= 0; --i)  //size_t为uint类型        {                cout << vec.at(i) << endl;        }        return 0;}

7.当在一个类中需要使用到static map对象或者static vector对象时,即所有的类对象共用一个stl对象或者自定义类对象,那么根据C++定义就必须在类实现外对static对象进行初始化,但是这几种类对象的初始化都是比较麻烦的,因此有一种解决办法就是,不在类中定义static map对象,而是直接在类体外进行定义,这样不仅类中可以使用该对象,而且也省去了初始化的麻烦。例:

//a.h#include <iostream>#include <map>using namespace std;class A{    public:        static A *getInstance()        {            static A a;            return &a;        }    private:        A(){}        ~A(){}            public:        void display();};

//a.cpp#include "a.h"static map<int, string>m_testMap;void A::display(){char *str[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};for(int i = 0; i < 7; ++i)m_testMap[i] = str[i];map<int, string>::iterator iter = m_testMap.begin();for( ; iter != m_testMap.end(); ++iter)cout << iter->second << endl;}int main(){        A::getInstance()->display();        return 0;}

输出结果:

MondayTuesdayWednesdayThursdayFridaySaturdaySunday

注:该类是不可重入的,即非线程安全的。

7.今天要完成一个功能,定时发系统公告,通过一个html页面提交表单获取发布公告的次数和时间间隔,然后执行一个发公告的php脚本,如果在php中通过sleep循环,这是可以做到的,但是非常耗费系统资源。那么, 可以通过linux系统提供的功能crontab完成。

(1)首先,将html页面提交的表单信息存储在一个文件中,php脚本每次执行就更新文件中的执行次数与间隔时间,当次数达到要求次数时则删除该行记录。

(2)设置定时执行该php,我们可以通过crontab -e命令编辑系统的crond脚本,因为该文件只能执行shell脚本或者可执行文件,所以不能直接将php文件写入其中,因此我们可以通过两种方法:

1)首先找到系统中安装的php执行程序,命令:which php可以找到,一般在/usr/local/bin/php,然后就可以执行php文件了,如需要执行的php文件为/data/text.php,则先检测该文件是否能够执行:/usr/local/bin/php -q /data/text.php,注:-q代表PHP 原本是应用在网页应用的﹐因此它内定会送出 HTML 的HEADER﹐但 是在此我们是要将 PHP 用作 Shell Script﹐"-q" 就是表示不要送 出HEADER 的意思.你可以试试看不加上 -q 的显示结果。然后通过crontab -e命令在文本中添加一行:
*/1 * * * * /usr/local/bin/php -q /data/text.php
表示一分钟执行一次。然后保存退出,再使用命令:/etc/init.d/crond restart重启crond。
2)php脚本一般都是通过apache等服务器执行的,因此可以通过curl访问php所在url来执行该php文件,
*/1 * * * * curl http://localhost/test.php

crond的具体使用方式参见:http://www.blogjava.net/decode360/archive/2009/09/18/287743.html

8.按位与位或位抑或运算都是根据二进制的补码来进行运算的,所以当为正数时补码为源码,否则为反码+1;

9.stl中如果需要声明map<>类对象中有vector结构时,如:map<int, vector<> >,需要将vector的两端的尖括号都跟map的尖括号保持一个空格,否则编译器会误以为<<或>>而报错。

10.securtCRT超时自动断开的问题:会话选项->终端->反空闲->发送协议NO-OP(P)勾选,时间设置为小于默认断开的时间,60秒就足够了。

11.今天用awk命令处理文本文件的编辑问题,要将一个类似于表格的文本中的数据输出到另一个文本,并且计算各列之和,如:

a 1 2 3 4 5

b 1 3 4 5 6

c 3 4 5 6 7

希望得到的结果是:

a 1 2 3 4 5

b 1 3 4 5 6

c 3 4 5 6 7

total 5 9 12 15 18

总共有72列,开始的想法是定义一个大小为72的数组,然后将每列的数据相加后存储到数组中,然后再输出,可是awk中貌似没有定义定长数组的说法,定义数组都是不需要长度的,然后就想到一个办法,定义一个二维数组,将整个表都输出到数组中,然后再处理数组,将数组中的列都相加后输出,命令是这样的:

cat file.txt | awk '{for(j = 2; j <= NF; ++j){ a[NR,j] = $j}}END{for(i = 0; i < NR; ++i) for(j = 2; j <= NF+1; ++j) {b[j] += a[i,j];} for(m in b) printf b[m]" "; printf "\n"}'


可是输出来的数据顺序跟表格文件中的数据顺序不一致,弄不清楚是为什么。后来过了段时间头脑清醒了后才发现自己笨的可以!根本不需要定义定长数组和二维数组就可以办到:

cat file.txt | awk '{for(j = 2; j <= NF; ++j) a[j] += $j} END{for(j = 2; j <= NF + 1; ++j) printf a[j]" "; printf "\n"}'


如此简单的问题却搞得那么复杂,哎。还遇到一个问题就是关于print与printf的区别,开始不清楚,每次输出都用print,然后发现每输出一个数据就会换行,很是纳闷。后来上网查了下后才发现应该用printf。两者的区别在于:print输出指定内容后换行,printf只输出指定内容后不换行。

12.如果一个函数定义为:

void func(string &str);

而很多时候调用这个函数接口都是直接通过传入字符串来的方便,如:

func("abc");

那么这里就会出现问题,因为字符串"abc"在内存中保存的位置是常量区,即const类型,而函数接口的形参是一个string引用,虽然string可以调用类型转换函数将char *类型转换成本身对象,但是如果是const char*编译器就会报错,如果不报错的话,那么就可以通过修改string对象而修改字符串"abc"了,所以要解决这个问题需要将函数接口定义为:

void func(const string &str);

这是最安全的方式。或者在调用函数前定义一个string对象:string str = "abc",然后再调用该接口:func(str);即可!

13.今天要求弄一个名字库,大概要50W个名字加入到数据库中,然后想办法就是先把百家姓弄出来,再把一些名字弄出来,在写两个循环把名字组合起来,但是在写脚本将名字和姓插入到数据库中遇见一些问题:

cat mingzi.txt | awk -F " " '{print "insert into db_name.t_mingzi value(\""$1"\");"}' |sort -u |  mysql -uroot -p******

但是却会报错,mingzi.txt这个文件的内容就是一行一个名字,没有空格。然后把打印的结果输出来觉得很奇怪:

");ert into db_name.t_mingzi value("抒洋");ert into db_name.t_mingzi value("家嘉");ert into db_name.t_mingzi value("俊南");ert into db_name.t_mingzi value("砚倾");ert into db_name.t_mingzi value("禹明");ert into db_name.t_mingzi value("奕平");ert into db_name.t_mingzi value("文水");ert into db_name.t_mingzi value("全灯");ert into db_name.t_mingzi value("小华");ert into db_name.t_mingzi value("锐宇

然后问了下同事才知道awk把名字后面的换行符也加进去了,所以会输出换行,然后在每行的末尾加一个空格符,这样根据awk的空格符间隔将换行符变成了$2,这样就解决问题了。

14.这几天要定时去跑几个脚本,使用crontab命令,每天凌晨的4点钟去跑的,但是第二天发现脚本根本没跑,大致是这样的:

总共4个perl脚本,然后将4个脚本全部加在了sh脚本中,内容是:

#!/bin/bash

./a.pl

./b.pl

./c.pl

./d.pl

纠结了几天也没解决这个问题到底是怎么回事,后来问了下同事,解决了。

crontab执行脚本时通常要注意环境变量,即一般情况下会在根目录下执行脚本的,所以执行的脚本一般都要用全路径,当我在根目录下执行这个脚本时会报错:

./a.pl: No such file or directory

./b.pl: No such file or directory

./c.pl: No such file or directory

./d.pl: No such file or directory

因为a.pl,b.pl等脚本的路径并不是在根目录,所以根本不能执行。必须在脚本内部加上执行的全路径,这样才能执行成功,所以需要在sh脚本中加上:

cd /data/;命令。。

15.gcc内联函数不能成为虚函数,原因:

所谓内联就是告诉编译器将代码嵌入到调用者的代码中,以增加执行码长度来换取执行的速度,因此内联函数已经不具有函数的特性,不能寻址。而虚函数是执行器动态转换的,需要在程序运行时动态读取虚函数表中的函数地址,故不能内联。

16.undefined reference to `vtable for ***`错误出现的原因:

今天在做项目的过程中出现了以上的编译错误,后来解决了,原因就是,当一个非抽象基类定义了虚函数但是并没有在文件中给出函数体的实现时,当有类继承自该基类并且没有重载该虚函数时就会出现以上编译错误,后面一般会给出更具体的错误信息,如:
In function `IBuffer':undefined reference to `vtable for IBuffer'(.rodata._ZTV13CStaticBufferILm61440EE[vtable for CStaticBuffer<61440ul>]+0x48): undefined reference to `IBuffer::GetFreeCapacity() const'(.rodata._ZTI13CStaticBufferILm61440EE[typeinfo for CStaticBuffer<61440ul>]+0x10): undefined reference to `typeinfo for IBuffer'

解决的办法是给出基类虚函数的实现。

还有一种情况是:当定义一个抽象基类时,如果把析构函数定义为纯析构函数而没有定义实现体时,继承该基类的类对象也会出现这种错误,因为当释放派生类对象时还是会调用基类的析构函数,不论是否为抽象类,最好的解决办法是将基类的析构函数定义为非pure并且给出实现体。

17.mysql concat函数:

该函数用来拼接字符串,可以将查询出来的结果拼接出来,但是如果查询一个字段为int类型,在进行拼接的时候如果不转换成字符串类型的话,那么拼接的结果就会出现乱码的问题。

如:

表t1字段为:a:varchar;

b:int(16);

select concat(a, b+"") from t1 limit 1;

这样得出的结果不会出现乱码的现象。

18.修改了一个项目中的头文件,则必须把所有包含该头文件的文件都需要重新编译一遍。否则这种情况产生的bug或者core dump非常难找。

为什么需要重新编译?原因:一个头文件是一个类或者结构在内存中的数据分布情况,如定义一个类头文件,则在定义完成后类中的成员变量,虚函数表的位置已经确定好了,如果这个时候修改头文件,比如改变了一个成员变量的顺序或者添加删除一个成员变量,而该类在内存中的数据分布如果不重新编译的话不会重新分布,因此当我们使用被修改的原来的成员变量时,使用的都是原来该成员变量在内存中所保存的数据,并且编译器不会报错,这个时候就特别容易引起非常隐秘的错误出现。而如果修改了虚函数,比如修改了一个参数,因为函数参数都是存放于内存堆栈中的,如果引用了被修改的参数时,只是使用了该参数原先在内存中的数据,也很容易引起错误。

在程序编译期时,编译器并不知道虚函数表中各函数的类型和属性等内容的,知道的只是该函数在虚函数表中的偏移位置,因此如果用&取该虚函数的地址得到的往往就是这个函数的偏移量。所以如果在虚函数列表中间位置添加一个虚函数,那么调用虚函数中根据偏移得到的函数实体往往就面目全非,特别容易产生难以察觉的bug。

总结:一旦修改了某个头文件,则必须把所有包含该头文件的文件都需要重新编译一遍。宁愿在编译期多花点时间,也总比在程序运行时core之后找bug半天都不一定找得到要来的好的多。

19.mysql union:

mysql执行联合查询时使用union,UNION用于把来自许多SELECT语句的结果组合到一个结果集合中。union的语法:

SELECT ...    
UNION[ALL | DISTINCT]   
SELECT ...    
[UNION [ALL | DISTINCT]   
SELECT ...]  


列于每个SELECT语句的对应位置的被选择的列应具有相同的类型。(例如,被第一个语句选择的第一列应和被其它语句选择的第一列具有相同的类型。)在第一个SELECT语句中被使用的列名称也被用于结果的列名称。 
 
SELECT语句为常规的选择语句,但是受到如下的限定: 

·只有最后一个SELECT语句可以使用INTO OUTFILE。 
·HIGH_PRIORITY不能与作为UNION一部分的SELECT语句同时使用。如果您对第一个SELECT指定了HIGH_PRIORITY,则不会起作用。如果您对其它后续的SELECT语句指定了HIGH_PRIORITY,则会产生语法错误。 

如果您对UNION不使用关键词ALL,则所有返回的行都是唯一的,如同您已经对整个结果集合使用了DISTINCT。如果您指定了ALL,您会从所有用过的SELECT语句中得到所有匹配的行。


20.samba:Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写,即为服务器消息块 ,SMB主要是作为Microsoft的网络通讯协议,后来Samba将SMB通信协议应用到了Linux系统上,就形成了现在的Samba软件。后来微软又把 SMB 改名为 CIFS(Common Internet File System),即公共 Internet 文件系统,并且加入了许多新的功能,这样一来,使得Samba具有了更强大的功能。

今天在内网服务器上面部署samba服务,希望能够跟wins系统实现文件共享,首先把配置修改完成后,将smbd和nmbd启动好了,然后通过win7网络映射驱动器连接内网服务器ip端口,但是一直显示不能成果,然后上内网服务器查看samba错误日志,提示为:

[2014/02/12 20:10:19, 0] smbd/service.c:make_connection_snum(1013)  '/data' does not exist or permission denied when connecting to [data] Error was 权限不够
以为是/data目录的权限问题,然后chmod 0777 /data 后发现问题还存在,上网搜索良久得到解决方案:

主要是selinux惹的祸,在不能从新启动机器的情况下,使用
   #setenforce 0
如果能从新启动机器,直接禁止selinux即可。

SElinux是Linux安全加强工具。关闭用setenforce 0或者修改文件vim /etc/sysconfig/selinux 把SELINUX=enforcing 改为 SELINUX=disabled.linux防火墙用chkconfig iptables on  开机启动 service iptables start 打开防火墙规则。

这里提示一下:安装和配置samba时,首先要确定服务器有该用户,然后才能通过smbpasswd -a添加用户并且设置密码,如:

# useradd test# smbpasswd -a test New SMB password: Retype new SMB password:

这样就能设置新用户密码了。


21.今天手贱,不小心把数据库里面的某个表删除了,心里那个悔啊!幸好不久前就已经做好了备份了,没办法,就只有恢复数据了。

总共10个数据库,删除了每个数据库中的一个t_titles表中的数据。首先将备份好的数据全部导入到另外一台服务器的备份数据库中,

for((i=0;i<10;++i));domysql -uroot -p* database_$i < $i.sqldone

执行这条shell语句就ok了。

然后将备份数据库中的那10个表中的数据挑出来:

for((i=0;i<10;++i));domysql -uroot -p* -e "select * from database_$i.t_titles" -N | awk '{print "insert into database_'$i'.t_titles values("$1","$2","$3");"}' done >titles.sql 
然后查看title.sql文件就会发现里面全是insert into语句。

然后在将这个文件转移到源服务器上面执行:

mysql -uroot -p1234 < titles.sql
就大功告成了。

有个问题需要注意的是,如果整个sql文件执行的中途出现一个错误的话,接下来的所有sql语句都不会执行,因此最好将

insert into 替换成 insert ignore into

表示忽略错误。


22.在编写C++代码的时候,经常会需要注意一些细节,最近就碰到了一个:

在代码中使用map存储数据的时候,如果key是一个自定义类的时候,需要同时在类中实现operator<函数,因为map的存储类型为红黑树,是有序的,如果不定义该函数的话,则map不能进行有效的数据存储。

#include <map>#include <iostream>using namespace std;typedef struct Inter{        int a;        int b;public:        Inter(int a1, int b1) : a(a1), b(b1){}        bool operator< (const Inter &int2) const        {                return a > int2.a;        }} Inter;int main(){        map<Inter, int>m_int;        Inter int1(1, 2);        m_int[int1] = 10;        Inter int2(3, 4);        m_int[int2] = 11;}

需要注意的是,operater<函数是const函数而且传入参数也需要是const引用,否则编译器会报错。

原创粉丝点击