打印限定长度字符串

1
2
3
char *s = "This my world.";
printf("Hello, %.5s!\n", s+8); printf("Hello, %.*s!\n", 5, s+8);
int minlen=5,maxlen=5; printf("Hello, %*.*s\n", minlen, maxlen, s+8);

打印后回填长度至参数’%n’

1
char *str = "world!"; int len = 0; printf("Hello %s\n%n", str, &len); printf(" = %d\n", len); // = 13

打印double格式’%f’

1
2
float f = 1.4; printf("%f", f);  //正确,f会被提升到double再用%f打印
double d = 1.4; printf("%f", d); //正确,若指定"%lf",则l无意义

implicit declaration of function ‘strdup’

#include <string.h>前面添加下面的其中任一宏定义

1
2
3
_SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500
|| _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L

或者在gcc编译选项内加上

1
-D_SVID_SOURCE

或者

1
-D_POSIX_C_SOURCE=200809L

编译链接动态库找不到libtcmalloc_minimal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
dpkg -L libtcmalloc-minimal0
/.
/usr
/usr/lib
/usr/lib/libtcmalloc_minimal.so.0.0.0
/usr/lib/libtcmalloc_minimal_debug.so.0.0.0
/usr/share
/usr/share/doc
/usr/share/doc/libtcmalloc-minimal0
/usr/share/doc/libtcmalloc-minimal0/TODO
/usr/share/doc/libtcmalloc-minimal0/AUTHORS
/usr/share/doc/libtcmalloc-minimal0/copyright
/usr/share/doc/libtcmalloc-minimal0/changelog.gz
/usr/share/doc/libtcmalloc-minimal0/README.gz
/usr/share/doc/libtcmalloc-minimal0/changelog.Debian.gz
/usr/lib/libtcmalloc_minimal.so.0
/usr/lib/libtcmalloc_minimal_debug.so.0

编译使用-lxxx默认会去环境变量对应库目录找xxx.so后缀的库文件,找不到libtcmalloc_minimal.so所以编译失败。下面有4个解决方法:

  1. 安装libtcmalloc_minimal0-dev之后就会有libtcmalloc_minimal.so文件
  2. 进入库目录,手动生成符号链接文件ln -s libtcmalloc_minimal.so.0.0.0 libtcmalloc_minimal.so
  3. 编译时指定真实文件绝对路径gcc test /usr/lib/libtcmalloc_minimal.so.0.0.0
  4. 编译时用-l指定文件全名-l:libtcmalloc_minimal.so.0.0.0

ctime使用

printf("%s", ctime(&time(NULL))); 本来以为可以省掉一个中间变量timer,而且显得高大上。编译时给出错误: 单目‘&’的操作数必须是左值,这段代码想直接对time()的返回值取地址,这是绝对不正确的,因为函数返回值是匿名变量,只能当右值,不可以做左值

打印带颜色和属性的字体

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
// foreground colours
printf("\033[30m black \033[m\n");
printf("\033[31m red \033[m\n");
printf("\033[32m green \033[m\n");
printf("\033[33m yellow \033[m\n");
printf("\033[34m blue \033[m\n");
printf("\033[35m magenta \033[m\n");
printf("\033[36m cyan \033[m\n");
printf("\033[37m white \033[m\n");

// background colours
printf("\033[40m black \033[m\n");
printf("\033[41m red \033[m\n");
printf("\033[42m green \033[m\n");
printf("\033[43m yellow \033[m\n");
printf("\033[44m blue \033[m\n");
printf("\033[45m magenta \033[m\n");
printf("\033[46m cyan \033[m\n");
printf("\033[47m white \033[m\n");

// other
printf("\033[0m default \033[m\n");
printf("\033[1m bold \033[m\n");
printf("\033[2m faint \033[m\n");
printf("\033[3m italic \033[m\n");
printf("\033[4m underlined \033[m\n");
printf("\033[5m slowblink \033[m\n");
printf("\033[6m rapidblink \033[m\n");
printf("\033[7m negative \033[m\n");

查看内存泄露

1
cat /proc/`pidof hello`/status |grep 'VmData:'

make传参

1
make CFLAGS=-m32 LDFLAGS=-m32  # 编译链接32位

64位系统编译32位libpcap

  • 报错/usr/bin/ld: 当搜索用于 /usr/lib/libnl-3.so 时跳过不兼容的 -lnl-3就安装lib32-libnl
  • 报错/usr/bin/ld: 找不到 -ldbus-1: 没有那个文件或目录就安装lib32-dbus

交叉编译术语

3种机器

  • Build machine: where the toolchain is built(用来构建gcc工具链的机器)
  • Host machine: where the toolchain will be executed(运行gcc工具链的机器)
  • Target machine: where the binaries created by the toolchain are executed(gcc工具链创建的二进制文件运行时所在的机器)

4种构建方式

  • Native build:BUILD==HOST==TARGET(三个都是x86)本机构建
  • Cross-build:BUILD==HOST!=TARGET(交叉构建BUILD==HOST==x86 TARGET==arm)在x86上编译出gcc工具链,在x86上使用该gcc编译出arm的程序
  • Cross-native build:BUILD!=HOST==TARGET(跨本机构建BUILD==x86 HOST==TARGET==arm)在x86编译出gcc工具链,把gcc工具链拷贝到arm,在arm用gcc编译出arm的程序
  • Canadian toolchain:BUILD!=HOST!=TARGET(加拿大工具链BUILD==x86 HOST==mac TARGET==arm)在x86上编译出gcc工具链,拷贝到mac,在mac上使用该gcc编译出arm的程序

configure参数

1
2
3
--build=BUILD           configure for building on BUILD [BUILD=HOST]
--host=HOST configure for HOST [guessed]
--target=TARGET configure for TARGET [TARGET=HOST]

如你在使用arm-none-linux-gnueabi-gcc,可设置--host=arm-none-linux-gnueabi --target=arm-none-linux-gnueabi,而--build会自动被设置

指定编译器

1
./configure CC=/tmp/arm/arm-linux-gcc CXX=/tmp/arm/arm-linux-g++

修改环境变量

1
2
3
4
export C_INCLUDE_PATH=${HOME}/path/to/include:$C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH=${HOME}/path/to/include:$CPLUS_INCLUDE_PATH
export LIBRARY_PATH=${HOME}/path/to/lib:$LIBRARY_PATH #编译时在这些路径下进行查找库
export LD_LIBRARY_PATH=${HOME}/path/to/lib:$LD_LIBRARY_PATH #运行时在这些路径下查找库

openssl

在第一个参数位置指定目标架构,-–cross-compile-prefix指定了命令前缀

1
2
./Configure linux-aarch64 --cross-compile-prefix=aarch64-himix100-linux- --prefix=/tmp/result && make && make install
#./Configure linux-armv4 --cross-compile-prefix=arm-himix200-linux- --prefix=/tmp/result && make && make install

若报错

1
2
3
4
crypto/aes/aes-x86_64.s: Assembler messages:
crypto/aes/aes-x86_64.s:2: Error: unrecognized symbol type ""
crypto/aes/aes-x86_64.s:3: Error: alignment too large: 15 assumed
crypto/aes/aes-x86_64.s:5: Error: bad instruction `xorl 0(%r15),%eax'

从错误打印看到,错误出现在编译 .s 文件(汇编文件)时,且后面还打印了汇编代码。原来 openssl 在编译时会默认使用汇编代码来加速编译过程,但只针对 x86平台,而 x86平台 的汇编代码和 arm平台 的汇编代码是不同的,所以会报错。加no-asm解决,表示不使用汇编代码加速编译

1
./Configure linux-aarch64 no-asm --cross-compile-prefix=aarch64-himix100-linux- --prefix=/tmp/result && make && make install

若报错

1
cc1: error: unrecognized command line option "-m64"

删除Makefile-m64

1
sed -i "s/ -m64//g" Makefile

在64位机器编译32位的openssl

setarch i386 ./config -m32./Configure -m32 linux-generic32./Configure linux-generic32 --shared

编译参数

-CFLAGS:C 编译器的选项,如指定头文件(.h文件)的路径,CFLAGS=-I/usr/include -I/path/include
-CXXFLAGS:C++ 编译器的选项。
-LDFLAGS:编译器会用到的一些优化参数,也可以在里面指定库文件的位置。LDFLAGS=-L/usr/lib -L/path/to/your/lib
-LIBS:告诉链接器要链接哪些库文件,如LIBS = -lpthread -liconvLDFLAGS告诉链接器库文件在哪个目录,LIBS是告诉链接器要链接哪些库文件

运行时找不到库,就需要在编译时给LDFLAGS增加-Wl,RLDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib

如果在./configure前就设置了环境变量export LDFLAGS="-L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib" ,那么在./configure后,Makefile将会设置LDFLAGS这个选项,链 接时会有这个参数,编译出来的可执行程序的库文件搜索路径就得到扩展了。

ldd查看程序运行缺的依赖库

1
2
3
4
$ ldd hello
...
libzlog.so.1 => not found
...

readelf查看库的soname

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
$ readelf -d /usr/lib/libzlog.so.1.2

Dynamic section at offset 0x18db8 contains 25 entries:
标记 类型 名称/值
0x0000000000000001 (NEEDED) 共享库:[libc.so.6]
0x000000000000000e (SONAME) Library soname: [libzlog.so.1]
0x000000000000000c (INIT) 0x4000
0x000000000000000d (FINI) 0x12884
0x0000000000000019 (INIT_ARRAY) 0x19da8
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x19db0
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x300
0x0000000000000005 (STRTAB) 0x18f0
0x0000000000000006 (SYMTAB) 0x6f0
0x000000000000000a (STRSZ) 2977 (bytes)
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0x1a000
0x0000000000000002 (PLTRELSZ) 3672 (bytes)
0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0x2858
0x0000000000000007 (RELA) 0x26a8
0x0000000000000008 (RELASZ) 432 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x000000006ffffffe (VERNEED) 0x2618
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x2492
0x000000006ffffff9 (RELACOUNT) 3
0x0000000000000000 (NULL) 0x0