Linux c/c++ 技巧总结

技术blog

C语言结构体里的成员数组和指针
https://coolshell.cn/articles/11377.html
Linux系统中“动态库”和“静态库”那点事儿
http://blog.jobbole.com/107977/
C++中new与malloc的10点区别
https://blog.csdn.net/linux_ever/article/details/50533149

book

高质量C++/C编程指南
https://yq.aliyun.com/articles/4864?spm=5176.100239.yqblog1.18.gKW5LN

动态库的使用

动态链接

这个比较常用,保证ldd时候可以找到对应的so,告诉连接器在哪找需要链接的so

动态加载

依赖linux的API,dlfcn.h中的几个方法dlerror、dlopen、dlsym、dlclose
dlopen中的filename:如果名字不以“/”开头,则非绝对路径名,将按下列先后顺序查找该文件。

  1. 用户环境变量中的LD_LIBRARY值
  2. 动态链接缓冲文件/etc/ld.so.cache
  3. 目录/lib,/usr/lib

flag表示在什么时候解决未定义的符号(调用)。取值有两个:

  1. RTLD_LAZY : 表明在动态链接库的函数代码执行时解决。
  2. RTLD_NOW :表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。

具体示例:

#include <dlfcn.h>
#include <stdlib.h>
#include "my_so_test.h"

void (*fn)();
int main() {
    void *handle = dlopen("./libtest.so", RTLD_LAZY);
    const char *err = dlerror();
    if (err != NULL) {
        perror("could not open shared object!");
    }
    fn = dlsym(handle, "testA");
    fn();
    fn = dlsym(handle, "testB");
    fn();
    dlclose(handle);
    return 0;
}

遍历目录内文件

Linux下的dirent.h头文件是专门为了获取文件夹目录内容而设计的结构体。使用示例如下:

#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>

void List(char* path, vector<string>& files)
{
    struct dirent* ent = NULL;
    DIR* pDir;
    char dir[512];
    struct stat statbuf;  
    if ( (pDir=opendir(path))==NULL )
    {
    fprintf( stderr, "Cannot open directory:%s\n", path );
        return;
    }
    while( (ent=readdir(pDir)) != NULL )
    {
        //得到读取文件的绝对路径名
        snprintf(dir, 512, "%s/%s", path, ent->d_name);   
        //得到文件信息
        lstat(dir, &statbuf);
        //判断是目录还是文件
        if ( S_ISDIR(statbuf.st_mode) )
        {
            //排除当前目录和上级目录
            if (strcmp(".",ent->d_name) == 0 || strcmp( "..",ent->d_name) == 0) 
                continue;
            //如果是子目录,递归调用函数本身,实现子目录中文件遍历
            printf( "子目录:%s/\n", ent->d_name );
            //递归调用,遍历子目录中文件
            //List(dir);
        }
        else
        {
            printf( "文件:%s\n", ent->d_name );
            files.push_back(pathName.assign(path).append("/").append(ent->d_name));
        }       
    }
    closedir(pDir);
}