c 和c ++总结_C/C++_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > C/C++ > c 和c ++总结

c 和c ++总结

 2013/9/16 20:46:26  saiyaren  程序员俱乐部  我要评论(0)
  • 摘要:1.0X00x0地址是NULL2.Gdb调试子进程1.setfollow-fork-mode<parent/child>这条命令可以用于在调试父进程或是子进程的模式之间进行切换。例如在fork函数执行之前执行setfollow-fork-modechild,当fork执行后,设定在子进程上的断点将会有效,而父进程上的断点此时无效;反之依然。缺省gdb是调试主进程的。2.attach<pid>GDB有附着(attach)到正在运行的进程的功能,即attach<
  • 标签:总结

1.???0X0

class="MsoNormal" style="font-family: 宋体, Verdana, Arial, Helvetica, sans-serif; font-size: 14.44444465637207px; line-height: 23.33333396911621px;">0x0地址是NULL

?

2.???Gdb调试子进程

1.set follow-fork-mode <parent/child>?

这条命令可以用于在调试父进程或是子进程的模式之间进行切换。例如在fork函数执行之前执行set follow-fork-mode child,?fork执行后,设定在子进程上的断点将会有效,而父进程上的断点此时无效;反之依然。缺省gdb是调试主进程的。

?

2.attach<pid>

GDB有附着(attach)到正在运行的进程的功能,即attach <pid>命令。因此我们可以利用该命令attach到子进程然后进行调试。

?

3.???Gdb调试nginx

多进程调试

#sudo gdb –q

gdbshell ./nginx

?

如果只是gdb ./nginx

那么启动nginx还是单进程

?

?

4.???Linux内核模块编写和makeFile编写

hello.c内容:

#include <linux/module.h>

#include <linux/init.h>

static int hello_init(void)

{

????????printk( KERN_ALERT " hello world enter \n");

????????return 0;

}

static void hello_exit(void)

{

????????printk(KERN_ALERT " hello world exit??\n");

}

module_init(hello_init);

module_exit(hello_exit);

?

MakeFile编写:

KERNEL_VERSION=/lib/modules/$(shell uname -r)/build

PWD=$(shell pwd)

default:

????????make -C $(KERNEL_VERSION) M=$(PWD) modules

注意上面的make –C需要时半角,而且前面需要有一个TAB,否则会执行失败

?

  一、模块加载函数:? (必须)

  module_init(initialization_funciton);

  二、模块卸载函数:???(必须)

  module_exit(cleanup_function);

  三、模块参数:

  module_param(参数名,参数类型,参数读/写权限)

  在模块插入时:?insmod???模块名???参数名=参数值

  eg:

  static char *book_name = " Linux?设备驱动?"

  static? int num = 4000;

  module_param(num, int , S_IRUGO);

  module_param(book_neme ,charp, S_IRUGO);

  参数类型:? byte, short, ushort, int uint, long , ulong, charp(字符指针)?bool,

  四、导出符号???(建议有)

  EXPORT_SYMBOL(?符号名/函数名)

  EXPORT_SYMBOL_GPL(符号名?/函数命)

  五、模块声明

  MODULE_LICENSE(" Dual BSD/GPL ");

  MODULE_AUTHOR (" XXXXX");

  MODULE_DESCRIPTION("XXXXX DRIVER");

  MODULE_VERSION(" XXXX VERSION");

  MODULE_DEVICE_TABLE(TABLE_INFO);

  MODULE_ALISA(XXXXXXX);

?

5.???内核编程中的EXPORT_SYMBOL

EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用??您还可以手工修改内核源代码来导出另外的函数,用于重新编译并加载新内核后的测试。

使用时注意事项:
在使用EXPORT_SYMBOL?.c文件中?需要?#include <linux/module.h>?文件。
//?
先写函数
func_a ()
{

}
//
再使用EXPORT_SYMBOL
EXPORT_SYMBOL(func_a);?
注:export出的函数必须为非static函数,且要在相应的.h文件中进行声明。?
??????
在内核中新加入文件时,需要对相应目录下的Makefile进行更改,并且新加入的文件使用的config设置与调用函数文件的config设置同。\\

?

6.???Sprintfprintf的区别

Sprintf是将一个格式化后的字符串输出到指定的字符串中;

Printf是将格式化后的字符串输出到屏幕中

?

?

7.???宏和函数在同名在一个头或者一个文件的作用

当宏和函数同名在一个文件中时,那么函数将被宏替换掉,执行宏的内容,因为宏在预编译时已经将内容替换。

一般这种写法都是用作注释函数的作用。

例子

#include "stdio.h"

void p(int a,int b,int c){

???printf("%s","test");

}

#define p(a,b,c)({(void)b,NULL;printf("%s","aaaa");})

int main(){

???p(1,2,3);

???printf("%s","hello world`");

}

?

上面代码执行后,输出的是aaaahello world

?

?

8.???结构体赋值并初始化

//结构体定义:

struct testa{

??int a;

};

//结构体赋值

struct testa sa={

???.a=1

};

?

?

9.???Gdb?加参数调试

首先进入GDB,然后设置断点

然后用set args?参数1?参数2 ….

然后执行r则可以进入到断点中了

?

?

10.?????????Strdup?复制字符串

原型:extern char *strdup(char *s);

  头文件#include <string.h>

  用法:char *strdup(char *s);

  功能:复制字符串s

说明:strdup()在内部调用了malloc()为变量分配内存,当程序结束后,必须用free()释放相应的内存空间,否则会造成内存泄漏

#include <stdio.h>

  #include <string.h>

  int main()

  {

  char *s="Golden Global View";

  char *d;

  clrscr();

  d=strdup(s);

  printf("%s",d);

  free(d);

  getchar();

return 0;

}

?

执行后输出Golden Global View,就是把s?的内容复制给了d

?

11.????????atoi?字符串转换为整数函数

?:?把字符串转换成整型数.

  名字来源:array to integer?的缩写.

  原型: int atoi(const char *nptr);

函数说明:?参数nptr字符串,如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,否则开始做类型转换,之后检测到非数字(包括结束符?\0)?字符时停止转换,返回整型数。

12.?????????Gdb?显示函数调用栈

打好断点后,执行后,执行bt命令则显示出函数的调用栈信息:

?

?

13.?????????gdb "value optimized out"原因

?是因为在编译时加入了编译优化参数,比如gcc -O2,导致变量在调试中不能读出。将编译参数-O去掉即可。.configure

?

14.?????strchr

 原型:extern char *strchr(const char *s,char c);

  const char *strchr(const char* _Str,int _Val)

  char *strchr(char* _Str,int _Ch)

  头文件:#include <string.h>

  功能:查找字符串s中首次出现字符c的位置

  说明:返回首次出现c的位置的指针,如果s中不存在c则返回NULL

返回值:Returns the address of the first occurrence of the character in the string if successful, or NULL otherwise

?

15.?????strtod

 strtod(将字符串转换成浮点数)

  相关函数

  atoiatolstrtodstrtolstrtoul

  表头文件

  #include<stdlib.h>

  定义函数

  double strtod(const char *nptr,char **endptr);

  函数说明

  strtod()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,到出现非数字或字符串结束时('\0')才结束转换,并将结果返回。若endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr传回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分。如123.456123e-2

?

?

16.?????Floor

函数名: floor

  功?:?返回小于或者等于指定表达式的最大整数

  用?: double floor(double x);

  头文件:math.h

?

17.?????Fprintf

  #include <stdio.h>

  int fprintf( FILE *stream, const char *format, ... );

  fprintf()函数根据指定的format(格式)(格式)发送信息(参数)到由stream()指定的文件. fprintf()只能和printf()一样工作. fprintf()的返回值是输出的字符数,发生错误时返回一个负值.

返回值:

若成功则返回输出字符数,若输出出错则返回负值。

?

?

例子:

#include <stdio.h>

int main(void)

{

FILE *stream;

if ((stream = fopen("testwrite.txt", "a")) == NULL) /* open file TEST.$$$ */

{

fprintf(stderr, "Cannot open output file.\n");

return 1;

}

s.i = 0;

s.ch = 'A';

//fwrite(&s, sizeof(s), 1, stream); /* ..struct..*/

?

int f=fprintf(stream,"%s %d\n","test aaa",123);

int fe=ferror(stream);

printf("%d %d",fe,f);

//printf("%s",f);

fclose(stream); /*....*/

return 0;

}

?

?

18.?????Ferror

 函数名: ferror

?:?在调用各种输入输出函数(?putc.getc.fread.fwrite)时,如果出现错误,除了函数返回值有所反映外,还可以用ferror函数检查。?它的一般调用形式为?ferror(fp);如果ferror返回值为0(),表示未出错。如果返回一个非零值,表示出错。应该注意,对同一个文件?每一次调用输入输出函数,均产生一个新的ferror?数值,因此,应当在调用一个输入输出函数后立即检?ferror函数的值,否则信息会丢失。在执行fopen函数时,ferror函数的初始值自动置为0

例子见17

?

在保障健壮性的情况下需要对文件的输出进行状态判断。

?

?

19.?????C中字符指针的赋值

赋值可以通过strcpysprintf来进行赋值

数值型的,需要先声明一个数值类型的变量,然后把变量赋值给指针

例:

char *a=(char*)malloc(sizeof(char)*100);

??int *b=(int*)malloc(sizeof(int)*8);

??strcpy(a,"\naaaa\n");

??printf("%s",a);

??sprintf(a,"%s%d%f\n","aaabbbbccc",123,1.23);

??printf("%s",a);

??*b=10;

??int c=100;

??*b=c;

??printf("%d\n",c);

??printf("%p\n",b);

??printf("%p",c);

??free(a);

??free(b);

?

?

20.?????malloc

mallocstdlib.h库下的

?

21.?????strcat

原型

  extern char *strcat(char *dest,char *src);

用法

  #include <string.h>

功能

  把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'

说明

  srcdest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

返回指向dest的指针。

?

?

22.?????????未声明(在此函数内第一次使用)

如果报了该错误,你声明的是外部全局变量,那么可能声明位置不对,你可以把你的变量放在文件的首部,这样就可以了。

?

?

23.?????????查看core_dump,然后调用堆栈

ulimit –c?是查看coredump的大小

ulimit –c 1024设置coredump大小,也可以通过unlimited设置(不限制

ulimit –c?后面跟随的是core file size?是文件的大小,单位是kb,1024就是1m512m就是1024*512

echo?"1" > /proc/sys/kernel/core_uses_pid使core文件名加上pid号,还可以用

mkdir -p /root/corefile

echo "/root/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern控制core文件保存位置和文件名格式。

以下是参数列表:
? ? %p - insert pid into filename?
添加pid
? ? %u - insert current uid into filename?
添加当前uid
? ? %g - insert current gid into filename?
添加当前gid
? ? %s - insert signal that caused the coredump into the filename?
添加导致产生core的信号
? ? %t - insert UNIX time that the coredump occurred into filename?
添加core文件生成时的unix时间
? ? %h - insert hostname where the coredump happened into filename?
添加主机名
? ? %e - insert coredumping executable name into filename?
添加命令名

?

当你执行二进制文件错误时,会生成一个coredump的文件在/root/corefile/目录下,然后通过gdb [exec file] [core file]?命令查看

:
gdb ./test?
/root/corefile/core-xxx-xxx

进入gdb后通过bt查看调用堆栈

?

普通用户,首先需要设置

ulimit –c unlimited

然后设置的

echo "/export/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

这个/export/目录,用户需要有写权限,如:chmod –R 775 /export

这样用户和组都有对该目录的写权限

?

如果想永久的保存该信息,那么则需要保存在环境变量配置中,如:

/etc/profile

~/.bashrc

24.??????G++编译

g++ test_mongodb.cpp -I /export/dev/usr/include/ /export/dev/usr/lib/libmongoclient.a /usr/lib64/libboost_thread-mt.so /usr/lib64/libboost_filesystem.so /usr/lib64/libboost_program_options.so -o test_mongodb

?

?

?

g++ test_mongodb.cpp -I /export/dev/usr/include/ -lmongoclient -L/export/dev/usr/lib/ -lboost_thread-mt -lboost_filesystem -lboost_program_options -L/usr/lib64/ -o test_mongodb

?

引入依赖库的库和动态链接库即可,注意路径,如/export/dev/usr/include/mongo

下面有个mongo目录,在cpp中引用的是mongo/….,那么这里就直接写include即可,如果cpp中没有写mongo?直接写的../../,那么外面编译时则需要加上/export/dev/usr/include/mongo

?

25.?????????error: default argument given for parameter 1 of误解决方法

/export/dev/hiphop-php/src/runtime/ext/ext_mongo.cpp:32: error: default argument given for parameter 1 of 'HPHP::c_Mongo::c_Mongo(const HPHP::ObjectStaticCallbacks*)'

当报如上错误时,是由于函数的参数默认值在声明时已经存在,而在实现时又重新定义,所以出现这个问题,所以在头文件中声明默认值后,在cpp文件中,实现时,参数就无需要在写默认值,如:

string Money::asString(bool shortVersion=true){

}

?

cpp

string Money::asString(bool shortVersion){}

就不需要重新声明默认值了

?

26.?????????编译c++错误

/export/dev/hiphop-php/src/runtime/ext/ext_mongo.cpp:31: error: expected unqualified-id before ':' token

?

编译时出现这个错误,是在31行:

c_Mongo:c_Mongo(const ObjectStaticCallbacks *cb): ExtObjectDataFlags<ObjectData::UseGet>(cb){

?

?}

?

注意c_Mongo:c_Mongo这里,正常的c++类函数实现应该是:

c_Mongo::c_Mongo

所以31行处少了一个引号,改为2个就可以了

?

/export/dev/hiphop-php/src/runtime/ext/ext_mongo.h:36: error: 'DBClientConnection' does not name a type

?

27.?????????获取环境变量

 函数名:?getenv

  ?:?从环境中取字符串,获取环境变量的值

  头文件:?stdlib.h

?:char *getenv(char *envvar);

?

28.?????????引用定义需要初始化

error: uninitialized reference member 'HPHP::c_Redis::c'

?

29.?????????报指针转换错误解决方法

/export/dev/hiphop-php/src/runtime/ext/ext_redis.cpp:36: error: cannot convert 'redis::base_client<redis::default_hasher>' to 'redis::client*' in assignment

当报如上错误时,可能是由于编译环境不同造成的,如:

redis::client *c;

boost::shared_ptr<redis::client> shared_c=boost::shared_ptr<redis::client>( new redis::client(host.data(),port));

c=*shared_c;

如上赋值把shared_c赋值给c会报上面的错误,所以改为如下方式:

c=&(*shared_c);

改成这样就没有问题了。

?

?

30.?????????Strace?查看调用函数

Strace –p?端口

31.?????????C拼接字符串乱码

char* varKey=(char*)malloc(varLen,1);

char* temp_varKey="mGet";

printf("%s\n",varKey);

当输出时,varKey是乱码

将分配空间语句改为:

char* varKey=(char*)calloc(varLen,1);即可

?

32.?????????报类型转换不匹配解决方法

error: invalid conversion from 'void*' to 'redisReply*'

当报如上错误时,是有如下语句造成的

reply = redisCommand(c,"SELECT %d",dbindex);

类型void不允许转换为'redisReply,这可能是由于编译器不同造成的,因为无法识别类别,如果我们知道类别,那么强转一下即可,如下:

reply = (redisReply*)redisCommand(c,"SELECT %d",dbindex);

这样就没有问题了,指定上'redisReply这个类型

?

33.?????????空指针判断和输出

通过printf输出指针

Char *a=NULL;

printf(“%p”,a);

输出如下值:

(nil)

就是空指针

判断空指针:

If(a==NULL){

?

}

?

?

34.?????????make: Nothing to be done for `all'解决方式

make clean

make

?

?

35.?????????gcc编译添加动态库

gcc test_redis_libevent.c -I??hiredis/ -I /export/dev/usr/include/ -levent -lhiredis -L/export/dev/usr/lib/ -o test_redis_libevent

-I?是添加文件夹(ai)

-levent?这里后面连接的是名字,找libevent这个库(小L

-L?是包的路径

?

36.?????????Mongo c++ limit

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

auto_ptr< DBClientCursor > mongo::DBClientBase::query???(????????const string &????????ns,

Query??????query,

int???nToReturn = 0,

int???nToSkip = 0,

const BSONObj *????fieldsToReturn = 0,

int???queryOptions = 0,

int???batchSize = 0

)???????

nToReturn?就是limit

?

37.?????????gdb list错误

(gdb) list analysis_result.cpp

Can't find member of namespace, class, struct, or union named "analysis_result.c????????????????????????????????????????????????????????????????????????????????????????pp"

这种写法有问题改为如下写法即可:

(gdb) list analysis_result.cpp:1

冒号后面是行号或者方法名称

?

?

38.?????????C++ std::set swap

Swap方法是交换2个集合内容

?

39.?????????头文件中写实现函数默认是内联

?

40.?????????C++set用法

使用set需要

#include <iostream>

#include <set>

using namespace std;

2个是必要的

?

声明一个set对象:

std::set<string> done;

<>间是他的类型

插入内容

done.insert(“test”);

根据类型不同可以插入不同对象;

Setfind使用

std::set <string> ::iterator test=done.find("test");

????if(test==done.end()){

????????cout<<"end"<<endl;

????}else{

????????cout<<"find"<<endl;

}

如果find中的内容在set内,那么则find的返回值不是setend,否则find内查找的内容set中不存在,那么返回值与setend是相等的。

?

?

41.?????????Gdb watch(观察点)使用

1 #include <iostream>

??2

??3 using namespace std;

??4

??5 int main(){

??6????cout<<"test gdb"<<endl;

??7????int a=0;

??8????for(int i=0;i<10;i++){

??9?????????a++;

?10????}

?11????cout<<a<<endl;

?12????return 0;

?13 }

?

在编译时:

g++ -g test_gdb.cpp –o tet_gdb

然后执行:

Gdb ./test_gdb

然后在6行打上断点

b 6

断点需要打在可以捕捉到观察点变量的位置,我们要观察的是a

然后运行程序,执行r

执行r后,进入断点

然后我们执行

Watch a

(gdb) watch a

Hardware watchpoint 2: a

这样便成功的加入了观察点,然后执行c

当观察点发生变化时:

Hardware watchpoint 2: a

?

Old value = 0

New value = 1

main () at test_gdb.cpp:8

8??????????for(int i=0;i<10;i++){

?

这里就进入了变化的位置

?

?

42.?????????__thread

线程局部变量修饰关键字,如:

__thread??int f;

?

43.?????????dynamic_pointer_cast?动态指针转换

boost:: dynamic_pointer_cast

这个是将指针动态向上转换,如:

Class A{

?

}

?

Class B:public A{

?

}

Int main(){

??boost::shared_ptr<A>?ptrBase?=?boost::shared_ptr<DeriveClass>(new?B());

boost::shared_ptr<B>?ptrDerive?=?dynamic_cast<boost::shared_ptr<B>?>(ptrBase);?

return 0;

}

这样就转换成功了。

?

44.?????????C++?的转换caozuofu.html" target="_blank">操作符

Class SmallInt{

?????????Public:

?????????SmallInt(int i=0):value(i){….}

?????????Operate int() constr{ return val;}

?????????Private:

?????????Std:size_t val;

}

?

C++的转换操作符的主要功能是做类型转换用途

如:

(1)只要存在转换,编译器将在可以使用内置转换的地方自动调用它:

SmallInt si;

double dval;

si >=dval;

(2)在条件中:

If(si)

(3)将实参传给函数或从函数返回值:

Int calc(int);

SmallInt si;

Int i=calc(si);

(4)作为重载操作符的操作数:

Cout<si<endl;

(5)显式转换:

Int ival;

SmallInt si=3.511;

Ival = static_cast<int>(si)+3;//转换siint

但是,这个不可以做2次类型强转,如:

Class Intergral{

?????????Public :

?????????Intergral(int i=0):val(i){}

?????????Operator SmallInt() const{return vale %256}

?????????Private:

?????????Std:size_t val;

}

?

Int calc(int);

Integral intVal;

SmallInt si(intVal);// intVal转换为?SmallInt

Int I =calc(si); //si转换为int

Int j =calc(intVal);//?错误,intVal不能二次转换为int

?

只能先将Integral?转换为SmallInt?,然后通过SmallInt转换为int,不能直接通过Integral转换为int,也就是转换操作符不能进行二次转换。

?

详细见:

C++ primer455-457

?

45.?????????c++?代码换行符

#define EXCEPTION_COMMON_IMPL(cls) \

??virtual cls* clone() { \

????return new cls(*this); \

??} \

??virtual void throwException() { \

????Deleter deleter(this); \

????throw *this; \

??}

?

C++中的宏需要在一行中定义,但是由时候代码过多,所以用\来进行换行标注

?

46.?????????C?可变参数实现

如:

int?demo(char?*msg,?...?)?

参见如下网页内容:

http://blog.csdn.net/weiqubo/article/details/4857567

?

47.?????????指针值

#include <stdio.h>

#include <malloc.h>

int main(){

????????int *a= (int *)malloc(sizeof(int));

????????int b=111;

???????????????????//指针地址

????????printf("%p-----\n",a);

???????????????????//指针的值

????????*a=b;

???????????????????//指针值

???????????????????printf("%d-----\n",*a);

???????????????????//指针地址

????????printf("%p-----\n",a);

????????free(a);

????????return 0;

}

?

输出:

0x209b010-----

111-----

0x209b010-----

?

?

48.?????????pthread_mutex_lock?互斥锁

pthread_mutex_lock

头文件:

  #include <pthread.h>

函数原型:

  int pthread_mutex_lock(pthread_mutex_t *mutex);

返回值:

在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

?

49.?????????C?断言assert使用

c语言中使用断言可以保证其健壮性,如果在断言的位置错误的时候,程序将终止;

例子:

#include <assert.h>

#include <stdio.h>

?

int main(){

????????assert(1==1);

????????printf("assert test!");

}

上面的是可以正常输出的,如果将

??assert(1==1);

换为

??assert(1==0);

?

报出如下错误:

test_assert: test_assert.cpp:5: int main(): Assertion `1==0' failed.

Aborted

断言失败,也就是该地方是false

断言使用的位置:

1)空指针。

2)输入或者输出参数的值不在预期范围内。

3)数组的越界。

?

不适合使用断言的位置:

 断言语句不是永远会执行,可以屏蔽也可以启用

  因此:

  1.不要使用断言作为公共方法的参数检查,公共方法的参数永远都要执行

2.断言语句不可以有任何边界效应,不要使用断言语句去修改变量和改变方法的返回值.

?

50.?????????C++ main?方法之前加载内容

我们都知道一个C++的程序要先从main函数执行起这是基本的编程常识但是我们却可以在main函数执行之前先来执行一段代码这是利用全局变量和构造函数的特性再有全局变量的时候要先创建全局变量然后在执行main函数

?

例:

#include <stdio.h>

static int label= 0;

?

class Test

{

??public:

????????Test();

};

?

Test::Test(){

????????label=11;

????????printf("call Test!");

}

?

Test test;

int main(){

//??????Test test;

????????printf("%d--\n",label);

????????return 0;

}

?

这样输出就会是:

call Test!11—

?

label已经被初始化好内容了

这是利用了构造函数初始化,构造函数加载在main之前了

?

如果把没有Test test;这行语句,那么久会输出

0—

?

51.?????????C语言中宏###的作用

http://blog.sina.com.cn/s/blog_95b655e001013jdc.html

例如下面的宏定义

#define STR( s ) #s

?

那么在程序中

printf("The string is %s/n", STR(OPEN) );

会被展开成

printf("The string is %s/n", "OPEN" );

?

也就是说,会对#后跟的参数加引号,使其变成一个字符串。

?

2. ##的作用是对文本进行连接

例如下面的宏定义

#define ?CONS( a, b ) a##e##b

那程序中

printf("the number is %d/n", CONS(2,3) );

会被展开成

printf("the number is %d/n", 2e3 );

?

?

需要注意的是,在有###的宏中,如果参数本身是宏,则这个参数宏不会展开。

加一层中间转换宏可以解决这个问题。

#define?_STR(s)?????#s?
#define?STR(s)??????_STR(s)??????????//?
转换宏?
#define?_CONS(a,b)??int(a##e##b)?
#define?CONS(a,b)???_CONS(a,b)???????//?
转换宏

?

?

52.?????????函数指针

#include <stdio.h>

?

int testcall(int &a);

?

int main(){

??int a=3;

??//testcall(a);

??//声明函数指针

??int (*f)(int &b);

??//给函数指针赋值

??f=testcall;

??printf("%d++\n",f(a));

??printf("f address %p,testcall address %p\n",f,testcall);

??printf("%d--\n",a);

??return 0;

}

?

int testcall(int &a){

????????a=a+1;

????????return a;

}

?

?

输出结果:

4++

f address 0x40060f,testcall address 0x40060f

4—

?

?

53.?????????boost::program_options的使用

参照:

http://www.rosoo.net/a/201109/14993.html

?

?

从命令行提取程序运行时选项的方法有很多。你可以自己编写相对应的完整的解析函数,或许你有丰富的C语言编程经验,熟知getopt()函数的用法,又或许使用Python的你已经在使用optparse库来简化这一工作。

program_options?
提供程序员一种方便的命令行和配置文件进行程序选项设置的方法。使用program_options库而不是你自己动手写相关的解析代码,因为它更简单,声明程序选项的语法简洁,并且库自身也非常小。将选项值转换为适合的类型值的工作也都能自动完成。库有着完备的错误检查机制,如果自己手写解析代码时,就可能会错过对一些出错情况的检查了。最后,选项值不仅能从命令行获取,也能从配置文件,甚至于环境变量中提取,而这些选择不会增加明显的工作量。

1.?首先看一个简单的程序吧:

#include?<string>?

#include?<iostream>?

#include?<boost/program_options.hpp>?

using?namespace?std;?

?

int?main?(int?ac,?char*?av[])?

{?

????boost::program_options::options_description?options("command?line?options");?

????options.add_options()?("help",?"Use?-h?or?--help?to?list?all?arguments")?

????????("file",?boost::program_options::value<string>(),?

?????????"Provide?input?file?name");?

????boost::program_options::variables_map?vmap;?

????boost::program_options::store(?

boost::program_options::parse_command_line(ac,?av,?options),?vmap);?

????boost::program_options::notify(vmap);?

?

????if?(vmap.count("help"))?{?

????????cout?<<?options?<<?endl;?

????}?

?

????if?(vmap.count("file")){?

????????cout?<<"Your?input?file:?"?<<?vmap["file"].as<string>()?<<?"\n";?

????}?

?

????return?0;?

}?

?

//compile:?g++?boost_test.cpp?-o?boost_test?-lboost_program_options?

程序的工作方式如下:
??? options_description?
类声明所有的有效命令行选项。
????
使用方法?add_options,您可以注册命令和跟在命令后面的参数类型。在此例中,help?选项不需要任何参数,但是?file?选项需要一个字符串参数。
??? variables_map?
类在运行时存储命令行选项及其参数。
??? Boost?
?parse_command_line?函数解析?argc??argv?参数。store??notify?方法帮助存储?vmap对象中的数据。
??? vmap.count()
用于检测输入的是哪个命令行参数,并采取适当的动作

2.?提供多个参数和缩写的命令选项

命令行处理通常同时需要同一个命令选项的短名称和长名称。此外,您通常必须多次使用某个选项,以便收集该选项的所有参数。例如,您可能希望使用?-h??--help?来打印可用的命令:

#include?<string>?

#include?<iostream>?

#include?<boost/program_options.hpp>?

using?namespace?std;?

?

int?main?(int?ac,?char*?av[])?

{?

??boost::program_options::options_description?options("command?line?options");?

??options.add_options()?("help,h",?"Use?-h?or?--help?to?list?all?arguments")?

????????????????????("file",?boost::program_options::value<vector<string>?>(?),?

?????????????????????????"Provide?input?file?name");?

??boost::program_options::variables_map?vmap;?

??boost::program_options::store(?

??????boost::program_options::parse_command_line(ac,?av,?options),?vmap);?

??boost::program_options::notify(vmap);?

?

??if?(vmap.count("help"))?{?

??????cout?<<?options?<<?endl;?

??}?

?

??if?(vmap.count("file"))?{?

??????vector<string>?ifiles(vmap["file"].as<?vector<string>?>?());?

??????vector<string>::iterator?vI;?

??????cout?<<?"Number?of?input?files:?"?<<?ifiles.size()?<<?endl;?

??????cout?<<?"Input?file?list:?"?<<?endl;?

??????for(vI?=?ifiles.begin();?vI?!=?ifiles.end();?++vI)?

??????????cout?<<?"\t"?<<?*vI?<<?endl;?

??}?else?{?

??????cout?<<?"No?file?specified\n";?

??}?

?

??return?0;?

}?

在使用?add_options?来添加命令选项时,较长和较短的选项之间使用逗号进行分隔。请注意,较长的选项(help)?必须在较短的选项?(h)?之前,代码才能正常工作。与使用单个字符串不同,file?选项现在是使用一个字符串向量来定义的。如果指定了?--file?选项多次,则会将所有收集到的file命令选项参数存储在关联的vector<string>中。下面是使用不同的参数来多次指定?--h??--file?所获得的输出:

?./a.out -h
command line options:
? -h [ --help ]???????? Use -h or --help to list all arguments
? --file arg??????????? Provide input file name

No file specified

./a.out --file abc --file pqr
Number of input files: 2
Input file list:
??????? abc
??????? pqr

3.?解析位置选项

下面的程序,第一个参数转换为?--file=<first parameter>,第二个参数转换为?--do-file=<second parameter>

#include?<string>?

#include?<iostream>?

#include?<boost/program_options.hpp>?

using?namespace?std;?

?

int?main?(int?ac,?char*?av[])?

{?

??boost::program_options::options_description?options("command?line?options");?

??options.add_options()?("help,h",?"Use?-h?or?--help?to?list?all?arguments")?

????????????????????????("file",?boost::program_options::value<string>(),?

?????????????????????????"Provide?input?file?name")?

????????????????????????("do-file",?boost::program_options::value<string>(),?

?????????????????????????"Specify?commands?file");?

?

??boost::program_options::variables_map?vmap;?

??boost::program_options::positional_options_description?poptd;?

??poptd.add("file",?1);?

??poptd.add("do-file",?2);?

?

??boost::program_options::store(?

??????boost::program_options::command_line_parser(ac,?av).?

??????options(options).positional(poptd).run(),?vmap);?

??boost::program_options::notify(vmap);?

?

??if?(vmap.count("file"))?{?

?????cout?<<?"file:?"?<<?vmap["file"].as<string>?(?)?<<?endl;?

??}?

?

??if?(vmap.count("do-file"))?{?

?????cout?<<?"do-file:?"?<<?vmap["do-file"].as<string>?(?)?<<?endl;?

??}?

?

??return?0;?

}?

下面是输出内容:

./a.out file1 dofile1
file: file1
do-file: dofile1

程序引入了新的类?positional_options_description。该类的?add?方法(add("command option", N))将位置?N?处的输入参数与命令行选项?"command option"?相关联。因此,./a.out file1?在内部解析为./a.out? --file=file1。另一个区别在于调用?program_options::store?方法的方式。与使用parse_command_line?例程不同,Boost?库要求您将?command_line_parser?例程与?store?方法结合在一起使用。

请注意,仍然可以使用?--file??--do-file?选项来调用该程序。最后,若要将所有的输入参数与同一个命令行选项相关联,您需要使用值-1?将该命令行选项添加到?positional_options_description?对象。下面是代码:


boost::program_options::positional_options_description poptd;
poptd.add("file", -1);
...

?

?

String test;

boost::program_options::value<string>(&test)

这样可以将值赋值给test

?

?

54.?????????Gdb?条件断点

使用gdb?调试时,如果想在某个条件触发时停下,那么可以这么做:

gdb test.cpp:7 if a == 1

这个就是当a?等于1时停下

但是在test.cpp中没有a这个变量,比如我们想在某个条件停下,但是其中的值非常复杂,那么我们就在代码内部自己先做一层逻辑,然后做一个临时变量a,然后再打断点时触发,即可

?

55.?????????设置全局变量

main方法的文件中定义一个全局变量如:

Int temp;

?

然后在需要使用该全局变量的文件中,声明:

extern int temp;

即可,注意只能放在外层,不能放在类内,否则会报如下错误:

/export/dev/hiphop-php/src/compiler/expression/scalar_expression.h:85: error: storage class specified for 'temp_gdb_hzg

?

56.?????????Vector?reserve

vector?reserve增加了vectorcapacity,但是它的size没有改变!而resize改变了vectorcapacity同时也增加了它的size
原因如下:
????? reserve
是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。

????? resize
是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。

??????
两个函数的参数形式也有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,?第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。

?

57.?????????BOOST_FOREACH用法

参照网址:

http://blog.csdn.net/jiangfriend/article/details/1713619

?

例子:

#include <string>
#include <iostream>
using namespace std;
#include <boost/foreach.hpp>
int main(int argc, char* argv[])
??? {
??? string str("The quick brown fox jumps over the lazy dog.");
??? BOOST_FOREACH(char c,str)
??? ??? {
??? ??? cout<<c<<endl;
??? ??? }
??? return 0;
??? }

?

这里的BOOST_FOREACH?就是foreach迭代器,前面的是一个obj对象,后面的是一个该对象类型的集合

?

?

58.?????????a storage class can only be specified for objects and functions

/export/dev/hiphop-php/src/compiler/test_gdb_hzg.h:6: error: a storage class can only be specified for objects and functions

?

Static class Test_Gdb_Hzg{

?????????….

};

?

由于在static?中没有添加变量名字;

?

Static class Test_Gdb_Hzg{

?????????….

}test;

这样声明上名字即可

?

?

59.?????????当头文件引用冲突时加入if def

?

.h?文件中加入:

?#ifndef __TEST_GDB_HZG_H__

?#define __TEST_GDB_HZG_H__

………

#endif

?

然后再多文件中引用就没有问题了

?

如果不这个,但文件引用会报如下错误:

has not been declared

当前文件中没有引入该头文件

?

如果引用了,会报重复声明了

?

所以在需要多文件引用时加入if def即可

?

60.?????????Vector back pop_back push_back

back?是获取尾元素;

pop_back是删除尾元素;

push_back是在尾部添加元素

?

61.?????????报未引用警告处理办法

当报了如下问题后:

/export/dev/hiphop-php/src/compiler/analysis/file_scope.cpp:413: warning: unused variable 'temp'

是由于声明了temp,但是后面未进行过调用,所以会报这个警告,这个不影响程序;

一般来说如:

Int temp=0;

Printf(“%d”,temp);

只要进行过调用就不会有问题了

?

62.?????????Gdb?读取vector数据

(gdb) p m_scopes

$89 =

??{

????{{

??????px = 0x7fffe0277120,

??????pn = {

????????pi_ = 0x7fffe0277700

??????}

????}??????{

??????px = 0x7fffe027d290,

??????pn = {

????????pi_ = 0x7fffe027dad0

??????}

????}????}

}

如上面这样的就无法用:

p??m_scopes[0].px读取了;上面是有2个数据

那么这样去读取:

p??m_scopes.back()[0].px

?

?

63.?????????~a取反的意思

?a?二进制为:110110

那么~a则为:001001

64.?????????C++ map操作

map中元素的查找:

?? find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器。????????

?? map<int ,string >::iterator l_it;;?
???
l_it=maplive.find(112);
???if(l_it==maplive.end())
??????????????? cout<<"we do not find 112"<<endl;
?? else cout<<"wo find 112"<<endl;

如果I_it!=maplive.end()时则是查找成功

?

其他map?操作详见:

http://blog.csdn.net/allovexuwenqiang/article/details/5686583

?

?

65.?????????gdb?读取first?second这样的vector?这样的值

p val

$37 = {

??first = {

???<std::tr1::__detail::_Hashtable_iterator_base<std::pair<HPHP::hphp_raw_ptr<HPHP::BlockScope> const, int>, false>> = {

??????_M_cur_node = 0x5f228e0,

??????_M_cur_bucket = 0x7fffc829f4e0

????}, <No data fields>},

??second = true

}

然后可以通过打印first

(gdb) p val.first

$38 = {

?<std::tr1::__detail::_Hashtable_iterator_base<std::pair<HPHP::hphp_raw_ptr<HPHP::BlockScope> const, int>, false>> = {

????_M_cur_node = 0x5f228e0,

????_M_cur_bucket = 0x7fffc829f4e0

??}, <No data fields>}

打印first的值

(gdb) p *val.first

$39 = (std::pair<HPHP::hphp_raw_ptr<HPHP::BlockScope> const, int> &) @0x5f228e0: {

??first = {

????px = 0x7fffc8276bc0

??},

??second = 2097152

}

就是在前面加星,如果想打里面的*val.first中的first,那么可以这样去打:

(gdb) p (*val.first).first

$41 = {

??px = 0x7fffc8276bc0

}

(gdb) p (*val.first).first.px

$42 = (HPHP::ClassScope *) 0x7fffc8276bc0

(gdb)

就是在值外面(*val.first)加上括号即可,然后调用first

也可以通过val.second调用value

?

?

66.?????????Std find查找

string variableName="$a->";

????if(variableName.find("->") != std::string::npos){

????????cout<<"++"<<endl;

}

查找到后会输出++

?

67.?????????Stl map erase使用

Erase是删除map?中的某个对象

map testMap;

testMap. Erase(name)

?

68.?????????函数指针用法

#include "stdio.h"

//函数指针类型定义?void?返回值类型?fun_ptr?类型名称; int是参数

typedef void (*fun_ptr)(int);

void test(int a){

????printf("%d==========\n",a);

}

?

int main(){

????test(1);

printf("%p\n",&test);

?????????//test的地址给t

fun_ptr t=test;

//执行t

????t(2);

????return 1;

}

t??test的地址一样

?

69.?????????linux?查看动态链接库的信息

ldd <可执行文件名>???????查看可执行文件链接了哪些??系统动态链接库

nm <可执行文件名>???????查看可执行文件里面有哪些符号

strip <可执行文件名>??????去除符号表可以给可执行文件瘦身

如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令

strings <可执行文件名>

?

?

70.?????????执行时报找不到动态链接库解决

执行编译语句:

gcc??--std=c99 -I/export/servers/mongodb_c/include/ -L/export/servers/mongodb_c/lib -o test_mongo_c test_mongo_c.c –lmongoc

编译成功后执行

./test_mongo_c时报了如下错误:

./test_mongo_c: error while loading shared libraries: libmongoc.so.0.7: cannot open shared object file: No such file or directory

通过ldd test_mongo_c?查看动态链接库,发现

linux-vdso.so.1 =>??(0x00007fff7c3c7000)

????????libmongoc.so.0.7 => not found

????????libc.so.6 => /lib64/libc.so.6 (0x00007f4afc602000)

????????/lib64/ld-linux-x86-64.so.2 (0x00007f4afcbbf000)

找不到??libmongoc.so.0.7这个库,那么我们用root用户登录,然后打开

/etc/ld.so.conf

这个文件,在/etc/ld.so.conf文件中,加入我们xx.so的目录即可,如:

/usr/local/lib

/export/servers/mongo/lib

然后保存后执行,/sbin/ldconfig –v这样就生效了,然后重新编译文件,再执行就可以了,并且执行ldd查看动态链接库也有内容了

?

?

71.??指针调用异常解决

printf("%d---\n",cursor.limit);

编译时报如下错误:

test_connect.c:39:26: error: request for member 'limit' in something not a structure or union

cursor是个指针不是结构体

所以应改为:

printf("%d---\n",cursor->limit);

这样调用即可

?

72.??error:???crosses initialization of 'time_t t'解决方法

当报如下错误时:

error:???crosses initialization of 'time_t t'

?

原代码:

case BSON_DATE:

??bson_printf( "%ld" , ( long int )bson_iterator_date( &i ) );

???struct tm *lt;

time_t time_value=bson_iterator_time_t (&i);

???………………….

???break;

?

case用花括号括起来即可编译通过

case BSON_DATE:

?{

??bson_printf( "%ld" , ( long int )bson_iterator_date( &i ) );

???struct tm *lt;

time_t time_value=bson_iterator_time_t (&i);

???………………….

???break;

?}

?

参照:

http://blog.sina.com.cn/s/blog_7a18bae10100s0lp.html

?

?

73.??socket?编程非阻塞

#include???<stdlib.h>

#include???<stdio.h>

#include???<unistd.h>

#include???<fcntl.h>

#include???<sys/types.h>

#include???<sys/socket.h>??

#include???<netinet/in.h>

#include???<errno.h>

#include???<time.h>

#include???<arpa/inet.h>

?

int???main(int???argc,???char???*argv[])

{

?????????int???fd,???retval;

?????????struct???sockaddr_in???addr;

?????????struct???timeval???timeo =???{3,0};

?????????socklen_t???len???=???sizeof(timeo);

?????????fd_set???set;

?

?????????fd???=???socket(AF_INET,???SOCK_STREAM,???0);

?????????if???(argc???==???4)???timeo.tv_sec???=???atoi(argv[3]);

?????????/*

???????????????????F_SETFL?设置文件描述词状态旗标,参数arg为新旗标,但只允许O_APPENDO_NONBLOCKO_ASYNC位的改变,其他位的改变将不受影响

???????????????????设置非阻塞O_NONBLOCK??(阻塞为~O_NONBLOCK)

?????????*/

?????????int???savefl???=???fcntl(fd,F_GETFL);

?????????fcntl(fd,???F_SETFL,???savefl???|???O_NONBLOCK);

?????????addr.sin_family???=???AF_INET;

?????????addr.sin_addr.s_addr???=???inet_addr(argv[1]);

?????????addr.sin_port???=???htons(atoi(argv[2]));

?????????printf( "%d\n ",???time(NULL));

?????????if???(connect(fd,???(struct???sockaddr*)&addr,???sizeof(addr))???==???0)

?????????{

???????????????????close(fd);

???????????????????printf( "connected..1\n ");

???????????????????return???0;

}

?

/*

???????????????????当连接状态为-1(connect),但是errnoEINPROGRESS

???????????????????表示此时tcp三次握手仍旧进行,如果errno不是EINPROGRESS,则说明连接错误,程序结束。

?????????*/

?????????if???(errno???!=???EINPROGRESS)

?????????{

???????????????????close(fd);

???????????????????perror( "connect..2 ");

???????????????????return???-1;

?????????}

??????????/*set清零使集合中不含任何fd*/

?????????FD_ZERO(&set);

?????????/*fd加入set集合*/

?????????FD_SET(fd,???&set);

?????????/*

???????????????????args0:最大的fd数量?最大值加1,不能错

???????????????????非阻塞机制

???????????????????args1:fd?set

???????????????????args2:fdset

???????????????????args3:fds错误的set

???????????????????args4?时间

???????????????????retval:

???????????????????负值:select错误?正值:某些文件可读写或出错?0:等待超时,没有可读写或错误的文件

?????????*/

?????????retval = select(fd + 1,???NULL,???&set,???NULL,???&timeo);

?????????if???(retval???==???-1)

?????????{

???????????????????close(fd);

???????????????????perror( "select ");

???????????????????return???-1;

?????????}

?????????else???if(retval???==???0)

?????????{

???????????????????close(fd);

??????????????????fprintf(stderr,???"timeout\n ");

???????????????????printf( "%d\n ",???time(NULL));

???????????????????return???0;

?????????}

?????????/*测试fd是否在set集合中*/

?????????if(FD_ISSET???(fd,&set))

?????????{

???????????????????int???error???=???0;?

???????????????????socklen_t???len???=???sizeof???(error);

???????????????????if(getsockopt(fd,???SOL_SOCKET,???SO_ERROR,???&error,???&len)???<??0)

{

printf???( "getsockopt??fail,connected??fail\n ");

return???-1;

???????????????????}

??????????????????

???????????????????if???(error???==???ETIMEDOUT)

???????????????????{

????????????????????????????printf???( "connected???timeout\n ");

???????????????????}

????????

???????????????????if(error???==???ECONNREFUSED)

???????????????????{

????????????????????????????printf( "No???one???listening???on???the???remote??address.\n ");

????????????????????????????return???-1;

???????????????????}

?????????}

?????????printf???( "connected???..???3\n ");

?????????fcntl(fd,???F_SETFL,???savefl);

?????????close???(fd);

????????

?????????return???0;

}

?

上面是一个连接超时验证的一个socket连接代码;

非阻塞连接参照:

http://hi.baidu.com/johntech/item/75ef7aea922cd23286d9dee1

?

注意:

1errno的值为111?ECONNREFUSED?),正确我应该需要的是115EINPROGRESS?

正确写法:errno?EINPROGRESS?

fd???=???socket(AF_INET,???SOCK_STREAM,???0);

int???savefl???=???fcntl(fd,F_GETFL);

fcntl(fd,???F_SETFL,???savefl???|???O_NONBLOCK);

错误:errnoECONNREFUSED?111

int???savefl???=???fcntl(fd,F_GETFL);

fcntl(fd,???F_SETFL,???savefl???|???O_NONBLOCK);

fd???=???socket(AF_INET,???SOCK_STREAM,???0);

?

记住错误红色部分需要在socket下面才对,先连接socket让,后在设置阻塞状态

Errno状态参照:

http://baike.baidu.com/view/3485007.htm

?

Socket函数:

头文件:

#include <sys/types.h>

#include <sys/socket.h>

函数原型?int socket(int domain, int type, int protocol);

例子:

fd???=???socket(AF_INET,???SOCK_STREAM,???0);

第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET;

第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_DGRAM、原始套接字SOCK_RAW(WinSock接口并不适用某种特定的协议去封装它,而是由程序自行处理数据包以及协议首部);

第三个参数指定应用程序所使用的通信协议。此参数可以指定单个协议系列中的不同传输协议。在Internet通讯域中,此参数一般取值为0,系统会根据套接字的类型决定应使用的传输层协议。

第三个参数protocol:

一般设置为0IPPROTO_IP 0),6IPPROTO_TCP

参照:

http://baike.baidu.com/view/9796742.htm

?

?

connect函数:

表头文件

#include<sys/types.h>

#include<sys/socket.h>

定义函数

int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

函数说明

connect()用来将参数sockfd?socket?连至参数serv_addr?指定的网络地址。结构sockaddr请参考bind()。参数addrlensockaddr的结构长度。

参数

参数一:套接字描述符

参数二:指向数据机构sockaddr指针,其中包括目的端口和IP地址

参数三:参数二sockaddr的长度,可以通过sizeofstruct sockaddr)获得

返回值

成功则返回0,失败返回-1错误码GetLastError()

参照:

http://baike.baidu.com/view/888434.htm

getaddrinfo函数

参照:

http://baike.baidu.com/view/6757218.htm

?

?

74.?????????c?指针

void test(int *a){

?????????//aa的地址,*a?是指向a的值

}

?

?

75.?????????error: no matching function for call to错误解决

报如下问题:

/export/dev_hhvm/hiphop-php_hzg/src/runtime/ext/ext_ice.cpp:39:55: error: no matching function for call to 'Ice::Communicator::stringToProxy(const HPHP::String&)'

?

是由于方法的参数不匹配造成的,如Ice::Communicator::stringToProxy(const HPHP::String&)

传入的类型是const HPHP::String&?,但是实际的类型是std::string,所以就会报这个问题了

?

?

76.?????????multiple definition of `HPHP::classInfoMap'

当编译时报了如下错误:

multiple definition of `HPHP::classInfoMap'

?

在头文件中定义了一个classInfoMap全局变量

Classinfo.h

std::map<std::string,int> classInfoMap;

?

这样定义全局变量时,需要在头文件在定义的变量前加上extern

extern Std::map<std::string,int> classInfoMap;

?

然后在cpp上进行一次声明即可:

std::map<std::string,int> classInfoMap;

?

?

?

77.?????????undefined reference to `HPHP::Ice_ClassInfo::Ice_ClassInfo()

当编译时报了如下错误:

/export/dev_hhvm/hiphop-php_hzg/src/runtime/ext/ext_ice.cpp:349: undefined reference to `HPHP::Ice_ClassInfo::Ice_ClassInfo()'

?

找到349行,发现时一个实例化语句如:

Ice_ClassInfo* ci = new Ice_ClassInfo();

但是Ice_ClassInfo这个类已经在头文件声明了

在头文件中找到了Ice_ClassInfo类:

Ice_ClassInfo();

发现只对Ice_ClassInfo类进行了构造函数的声明,并没有实现,所以报了没有引用的问题,

那么我们在cpp中进行实现的定义或者在头文件中

Ice_ClassInfo(){};这样实现即可

?

?

78.?????????undefined reference to `vtable for SequenInfo‘

当编译时,报了如下错误:

undefined reference to `vtable for SequenInfo‘

?

提示虚函数表没有SequenInfo声明这个类,

这是由于我的SequenInfo中有一个虚函数在基类中没有声明,所以删除掉SequenInfo类中的在基类中没有用到的虚函数即可编译通过,而且需要注意的是,使用多态时,子类和基类都需要实现构造和虚构函数,并且实现虚函数,否则都会出现如上错误;

例:

Class Base{

public:

?????????Base(){};

???????~Base(){};

?????????virtual bool usesClasses(){};

};

?

Class SubClass{

?????????public:

???????????????????SubClass(){};

???????????????????~ SubClass(){};

???????????????????virtual bool usesClasses(){};

???????????????????/*

????????????????????????????这个虚函数在实例化SubClass时就会报如上错误,因为在Base类中没有定义这个虚函数,所以删除它即可,而且上面的构造函数,虚构函数都需要对应实现

???????????????????*/

???????????????????virtual bool getId(){};

}

?

?

79.?????????List?用法

#include <iostream>

#include <list>

using namespace std;

?

class A{

????????public:

????????????????int v;

????????????????list<A> next;

};

int main(){

????????list<A> test_list;

????????for(int i=0;i<4;i++){

????????????????A *a=new A();

????????????????a->v=i;

????????????????list<A> list;

????????????????A *b=new A();

????????????????b->v=i+2;

?????????????????????????????????????//插入内容

????????????????list.push_back(*b);

????????????????a->next=list;

????????????????test_list.push_back(*a);

????????}

????????list<A>::iterator itr;

???????????????????//遍历

????????for(itr=test_list.begin();itr!=test_list.end();itr++){

????????????????cout<<itr->v<<endl;

????????????????list<A>::iterator itr_n;

????????????????for(itr_n=itr->next.begin();itr_n!=itr->next.end();itr_n++){

????????????????????????cout<<"==================="<<endl;

????????????????????????cout<<itr_n->v<<endl;

????????????????}

?

????????}

????????return 0;

}

?

?

80.?????????syscall exception: Resource temporarily unavailable

pthread_create?报了如下错误:

?

syscall exception: Resource temporarily unavailable

?

有几种暂时解决方式:

(1)???????ulimit –u 65535?这样是设置是改子进程数量

(2)???????ulimit –a查看

然后修改?ulmit?–s 1024?是修改stack size也就是线程栈的大小

?

还有代码解决方式

?

?

81.??????Gdb?根据地址和类型取值

p {VolumePath} 0x6141d60

?

p {类型}?地址

?

?

82.?????????source?type?is not polymorphic

c++?使用

P_ClassInfo *p_classInfo=dynamic_cast<HPHP::P_ClassInfo*>(ismc->typeInfo);

转换是报了如下错误:

source type is not polymorphic

源类型不是多态,那么是由于在类中没有定义虚函数

?

?

83.?????????crosses initialization

当编译器报如下错误时:

error:???crosses initialization of 'HPHP::P_PrimitiveInfo* p_primitiveInfo'

?由于?switchcase后面没有加大括号,因为

如果大括号,则会出现crosses initialization错误,因为编译器会认为局部变量i可能会被绕过申明而被直接进入其作用域。

见:

http://blog.sina.com.cn/s/blog_489239370100asc4.html

?

?

84.?????????test.cpp:16:47: error: 'malloc' was not declared in this scope

c++?编译报了这个错误,添加个头文件就可以;?

#include<stdlib.h>

?

?

85.?????????安装libevent报错解决

当执行make?时,libevent报了如下错误,由于libtool版本产生的

Version mismatch error.??This is libtool 2.4, but the libtool: definition of this LT_INIT comes from libtool 2.2.6b

解决方法下载libtool2.2.6b,然后安装,需要默认安装,配置环境变量不知道为何无作用

安装完毕后解决该问题

?

86.?????????Const char*?强转为?char *

const char * str = "asd";

char* p =const_cast<char*>(str.c_str());

?

87.?????????int?转换成枚举类型

如枚举类型为:

Enum Kind{

?????????Kind_a,

?????????Kind_b,

?????????Kind_c

} kind;

?

Int a=1;

kind=Kind(a);

红色部分是强转方法;

?

?

发表评论
用户名: 匿名