转载请注明出处。https://rhirufxmbcyj.gitlab.io
strdup 和 _strdup 的使用及区别
二者区别:
strdup是POSIX,_strdup是Windows特定。 在Unix上,使用的strdup。
跨平台宏定义
在不同操作系统的lib库名字不同的,为了让程序可以多平台,需要在宏定义中判断当前运行操作系统和编译器的类型,动态调整。
- 操作系统判定:
1 | Windows: WIN32 _WIN32 |
- 编译器判定:
1 | Borland: __BORLANDC__ |
- 操作系统位数判定:
1 | Linux_x32: __i386__ |
pthread相关
#include <pthread.h>
pthread并非Linux系统的默认库,而是POSIX线程库,在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。函数执行错误信息作为返回值返回。
- 创建线程
1 | int pthread_create( |
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
- 等待线程结束
1 | int pthread_join(pthread_t thread, void **retval); |
互斥锁
- 初始化 pthread_mutex_t 动态创建的需要用pthread_mutex_init( )初始化,释放内存必须用pthread_mutex_destroy( )销毁。静态创建的用PTHREAD_MUTEX_INITIALZER赋值。
- 锁上互斥锁 pthread_mutex_lock( )
- 解锁互斥锁 pthread_mutex_unlock( )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void *fun1(void *arg)
{
pthread_mutex_t *temp = (pthread_mutex_t *)arg;
pthread_mutex_lock(temp);
for(int i=0;i<5;i++)
{
sleep(5);
}
pthread_mutex_unlock(temp);
return 0;
}
void *fun2(void *arg)
{
pthread_mutex_t *temp = (pthread_mutex_t *)arg;
pthread_mutex_lock(temp);
pthread_mutex_unlock(temp);
return 0;
}
int main()
{
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,fun1,&mu);
pthread_create(&thread2,NULL,fun2,&mu);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
pthread_mutex_destroy(&mu);
return 0;
}
示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/
pthread_join(t_a, NULL);/*等待进程t_a结束*/
pthread_join(t_b, NULL);/*等待进程t_b结束*/
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
void *thread1(void *junk)
{
for(i=1;i<=6;i++)
{
pthread_mutex_lock(&mutex);/*锁住互斥量*/
printf("thread1: lock %d/n", __LINE__);
if(i%3==0){
printf("thread1:signal 1 %d/n", __LINE__);
pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
printf("thread1:signal 2 %d/n", __LINE__);
sleep(1);
}
pthread_mutex_unlock(&mutex);/*解锁互斥量*/
printf("thread1: unlock %d/n/n", __LINE__);
sleep(1);
}
}
void *thread2(void *junk)
{
while(i<6)
{
pthread_mutex_lock(&mutex);
printf("thread2: lock %d/n", __LINE__);
if(i%3!=0){
printf("thread2: wait 1 %d/n", __LINE__);
pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/
printf("thread2: wait 2 %d/n", __LINE__);
}
pthread_mutex_unlock(&mutex);
printf("thread2: unlock %d/n/n", __LINE__);
sleep(1);
}
}
跨平台踩坑
- printf(“%s”,a);a不能为NULL否则会报错
- Visual GDB(后面使用VG表示) 调试某一个测试程序。VG不能指定编译和调试某一个程序(比如gtest程序),
如果需要调试指定的程序需要在VisualGDB Project Properties ->Debug setting ->debug->Debugged executable 中设置启动的程序就可以调试指定的程序了 - VG运行制定gtest 在VisualGDB Project Properties ->Debug setting ->debug->Main executable arguments 中指定
gtest的名称就可以运行指定路径的gtest –gtest_filter=case2.* - linux long 和 long long 都是8字节,windows下的long是4字节,需要把windows下的long改成int使用
- visualGDB打开的工程中不能识别include目录,需要在 工程->右键属性->配置属性->VC++目录->包含目录中手动把src目录添加进去,否则inlcude的时候需要使用..去寻找完整路径。
例如 不配置的话 #include “base/base.h”就不能识别到,需要使用#include “../base/base.h” - CMakeLists.txt中依赖静态库语句中,被依赖的库名需放在依赖库名后
例如 target_link_libraries(main test1 test2 test3 test4)
test2依赖test4,test4就需要放test2后边 - linux和mac中没有类似windows中的_DEBUG宏
linux下动态库去符号(仅适用动态库):
原文:https://blog.csdn.net/passers_b/article/details/7582535
推荐第二种方法
1、使用GCC 的C++ visibility 支持。
把attribute ((visibility (“default”))) 放置在你希望导出的struct,class,function的声明处,然后修改你的GCC构建参数,使用 -fvisibility=hidden 参数编译每一个源代码文件。GCC编译源代码文件的visibility默认属性是public,所以默认所有符号都导出来了,设置为hidden后然后在需要导出的地方加attribute ((visibility (“default”))),以达到控制导出符号的目的。在跨平台代码的编写中,常使用下面类似的宏定义来简化上述过程。
1 |
|
2、使用链接参数 –retain-symbols-file 控制静态符号表,–version-script 控制动态符号表,后面都是接含有导出符号的文件的名字。这两个参数在移植windows下的动态库很有用,windows下的DEF文件能控制导出符号,我们可以在linux下的构建脚本中解析DEF生成一个导出符号文件,然后作为retain-symbols-file,version-script的参数。
编译链接方法:gcc a1.c -shared -o liba1.so -Wl,–retain-symbols-file=a1.sym -Wl,–version-script=a1.map
1
2
3
4
5
6
7
8
9
10 a1.sym写法:控制.symtab节
func_1
func_3
a1.map写法:控制.dynsym节
{
global:
func_1;
func_2;
local: *;
};
一般编译会加-s将.symtab节删除掉,过删除的话就可以不加a1.sym