C/C++笔记

动态库加载

介绍动态库文件(so文件)加载的相关内容,包括动态库dl的基本使用,利用LD_PRELOAD给glibc库函数添加钩子/系统钩子,C++中动态库加载和设计等。

dl库使用:dlopen APIs

dl库主要包括dlopen dlsym dlclose dlerror四个接口。

#include <dlfcn.h>

void *dlopen(const char *filename, int flag);

char *dlerror(void);

void *dlsym(void *handle, const char *symbol);

int dlclose(void *handle);

//Link with -ldl.
  • dlopen(filename, flag)

dlopen会在特定的目录下查找filename,默认如/lib;/usr/lib;LD_LIBRARY_PATH;/etc/ld.so.cache等,但是不包括当前目录。如果需要当前目录,需要加上./来标识。dlopen('./module.so', RTLD_LAZY)

一些特定的FLAG标识了符号绑定的时间、顺序和可见范围,常用的有RTLD_LAZY RTLD_NOW RTLD_GLOBAL RTLD_NOLOAD(常用于重新修改SO文件的Flag)

  • dlsym(handle, symbol)

有两个特殊的伪handle用于dlsym操作,RTLD_DEFAULT和RTLD_NEXT,通常会被用来做函数钩子。

  • error_dlsym = dlerror()

用于获取dl库函数出错的原因。但dlsym接口在某些情况下执行正确也会返回NULL,因此只能通过dlerror()的返回值error_dlsym来判断是否出错。

// reset errors
    dlerror();
    hello_t hello = (hello_t) dlsym(handle, "hello");
    const char *dlsym_error = dlerror();
    if (dlsym_error) {
        cerr << "Cannot load symbol 'hello': " << dlsym_error <<
            '\n';
        dlclose(handle);
        return 1;
    }
  • dlclose(handle)

所有由dlopen打开的句柄理论上应该由dlclose()释放。


关于const和引用的重载

最近学习C++11新特性右值引用的过程中重新复习了一下引用,重载等概念,总结一下:

const与引用(&)修饰

const与引用是对参数调用过程中的修饰,在函数重载时,有些时候加或者不加修饰符是会引发冲突。

void fun1(int &)
{
}
void fun1(int const)
{
}

以上述代码为例,总结出了一下几种组合是否会出现redefinition冲突

无修饰const&const + &
无修饰xoo
constxoo
&ooo
const + &ooo

从上表可以看出,对于非引用类型,const不能作为签名的区分,对引用类型没有这个限制。引用可以作为签名的区分。但是在函数调用时,由于调用实参的类型不同,会导致调用方法的二义性(ambiguous)。


C++11 共享内存

关于cout共享:

//描述: t1: 使用cout输出"thread function\n" main:使用cout输出"main thread"
//问题: 两个不同线程(t1 main)对cout的使用会产生冲突
//解决:使用std::mutex解决
#include <mutex>
std::mutex mu;
void shared_cout(std::string s1, int id)
{
    mu.lock();
    std::cout << s1 << id << std::endl;
    mu.unlock();
} 

只读的数据不会有数据竞争问题


STL与std::algorithm

algorithm

STL 学习

STL:: 功能What 底层实现How 算法优势Why

count: 返回searchValue出现的次数,功能类似于find;

vector<int> ivec;
cout<<count(ivec.begin() , ivec.end() , searchValue);

count_if: 返回区间中满足条件的元素

#include <vector>
#include <algorithm>
#include <iostream>

bool greater10(int value)
{
    return value >10;
}

int main()
{
    using namespace std;
    vector<int> v1;
    vector<int>::iterator Iter;

    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(10);
    v1.push_back(40);
    v1.push_back(10);

    cout << "v1 : ";
    for (Iter = v1.begin(); Iter != v1.end(); Iter++)
       cout << *Iter << " ";
    cout << endl;


    vector<int>::size_type  result1 = count_if(v1.begin(), v1.end(), greater10);  //count_if算法返回使谓词函数返回条件成立的元素个数
    cout << "The number of elements in v1 greater than 10 is: "
         << result1 << "." << endl;

    return 0;
}

operator++的重载

一般类型会重载operator++的两种形式,无参数/前缀版本operator++()和带int参数的后缀版本operator++(int)。其中,后缀版本在调用时会被编译器自动标注为a.operator++(0)

注意:这两个函数的返回值:前缀版本:A&,后缀版本:A,或者会加上常量修饰符const A

通常,在后缀版本的实现中会调用前缀版本函数。

#include <iostream>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <memory>

class UPInt {
public:
  UPInt() : value(0) {
  }

  UPInt& operator++() {
    *this += 1;
    return *this;
  }

  const UPInt operator++(int) {
    UPInt old = *this;
    this->operator++();
    return old;
  }

  UPInt& operator+=(int rValue) {
    value += rValue;
    return *this;
  }

  int getValue() {
    return value;
  }

protected:
  int value;
}; 

using namespace std;
int main()
{
    UPInt i;
    cout << &i << endl;
    cout << &(i++) << endl; 
    //std::cout << va2.size() << std::endl;
}

vector**:

  • v2(v1.begin(), v2.end()-1)
  • size
  • push_back
  • begin/end
  • T& front /back (都返回引用)
  • void pop_back (删除尾部元素)
  • operator []
  • erase(v1.begin()) / erase(v1.begin(), v1.begin()+2)
  • insert(v1.begin(), 100)

string:

  • str1(10, ‘a’)
  • length()

bind使用

它提供一个任意的函数对象(仿函数)、函数、函数指针、成员函数指针。 它可以绑定任意的参数。bind 没有对函数对象有任何的要求。返回值是一个函数对象。

#include <iostream>
#include <functional>
#include <memory>
using namespace std;

class A
{
public:
    A(int a = 0)
    {
        this->a = a;
    }
    void print(int c)
    {
        std::cout << a << " " << c << std::endl;
    }

    static void print2(int c)
    {
        std::cout << c << std::endl;
    }
private:
    int a;
};

struct Func {
    void operator()(int x) {
        cout << x << endl;
    }
} f;

int main()
{
    A a[2] = {1,2};
    bind(A::print, a, placeholders::_1)(3);
    bind(A::print, a[0], placeholders::_1)(3);
    bind(A::print, shared_ptr<A>(new A()), placeholders::_1)(3);
    //
    bind(A::print, a+1, placeholders::_1)(4);
    bind(A::print2, placeholders::_1)(42);
    //对于函数对象,可能还需要指明返回值类型
    bind<void>(f, 3)();
}
#ouput
1 3
1 3
0 3
2 4
42
3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值