C++(98/11)问题 (2)

多线程问题(续)

线程可以独立运行,但是同时又和同进程的其他线程共享资源,这就造成在需要获取共同资源的时候需要竞争对于资源的使用,所有的关于线程的使用都是在设计如何竞争环境下使用共同的资源,以及更高效的问题

线程之间共享数据

  • 互斥量 std::mutex,对于mutex的变量有lock和unlock来控制。此外,还有lock_guard来在构造锁定 析构是解锁。
std::list<int> some_list;
std::mutex some_mutex;

void add_to_list(int new_value)
{
    std::lock_guard<std::mutex> guard(some_mutex);
    some_list.push_back(new_value);
}
bool list_contains(int value_to_find)
{
    std::lock_guard<std::mutex> guard(some_mutex);
    return std::find(some_list.begin(),some_list.end(),value_to_find)
        != some_list.end();
}

main


int main()
{
    add_to_list(4);
    std::cout<<"contains(1)="<<list_contains(1)<<", contains(42)="<<list_contains(4)<<std::endl;
}

这是一个简略的示例,但是在实际情况下,指针和引用指向的数据需要仔细的设计好。

死锁避免的一些规则

避免嵌套锁
持有锁时,避免调用未知代码
获取锁时,按照固定的顺序,不要随意调整
锁的层次 thread_local的使用

多线程异步计算: condition_variable future promise async

condition_variable

bool more_data_to_prepare()
{
    return false;
}

struct data_chunk
{
};

data_chunk prepare_data()
{
    return data_chunk();
}

void process(data_chunk&)
{
}

bool is_last_chunk(data_chunk&)
{
    return true;
}

std::mutex mut;
std::queue<data_chunk> data_queue;
std::condition_variable data_cond;

void data_preparation_thread()
{
    while(more_data_to_prepare())
    {
        data_chunk const data = prepare_data();
        std::lock_guard<std::mutex> lk(mut);
            
        data_queue.push(data);
        data_cond.notify_one();
    }
}

void data_processing_thread()
{
    while(true)
    {
        std::unique_lock<std::mutex> lk(mut);
        data_cond.wait(lk,[] { 
            return !data_queue.empty();
            });   // 条件等待
        data_chunk data = data_queue.front();
        data_queue.pop();
        
        lk.unlock();
        process(data);
        
        if(is_last_chunk(data))
            break;
    }
}

在两个线程中分别执行

int main()
{
    std::thread t1(data_preparation_thread);
    std::thread t2(data_processing_thread);
    
    t1.join();
    t2.join();
}

future & promise

int fun1()
{
    cout<< "find the anser"<<endl;
    return 42;
}

void fun2()
{
    cout<< "do other stuff"<<endl;
}

int main()
{
    std::future<int> answer = std::async(fun1);
    fun2();
    std::cout<<answer.get()<<std::endl;
}

ex2

#include <future>
#include <vector>
#include <iostream>       
#include <functional>     
#include <thread>        
#include <numeric>      //  accumulate

using namespace std;
void accumulat( vector<int>::iterator first,
     vector<int>::iterator last,
     promise<int> &accumulate_promise)
{
    int sum =  accumulate(first, last, 0);
    accumulate_promise.set_value(sum);  // Notify future
}

int main(int argc, char *argv[])
{
    try {
         vector<int> numbers = { 1, 2, 3, 4, 5, 6 };
         promise<int> accumulate_promise;
         future<int> accumulate_future = accumulate_promise.get_future();
         thread work_thread(accumulat, numbers.begin(), numbers.end(), ref(accumulate_promise));
        //accumulate_future.wait();  
         cout << "result = " << accumulate_future.get() << '\n';
        work_thread.join();  // wait for thread completion
    }
    catch ( exception &e)
    {
         cerr << e.what();
    }
    return 0;
}

内存模型

  • 对同一段内存修改的未定义行为
  • atomic原子类型的存储 memory order问题
    store
    load
    读写顺序模型

atomic类型的操作:
除了一组通常的操作(load()、store()、exchange()、compare_exchange_weak()和compare_exchange_strong())之外,像std::atomic<int>或者std::atomic<unsigned long long>这样的原子整型还有相当广泛的一组操作可用:fetch_add()、fetch_sub()、fetch_and()、fetch_or()、fetch_xor(),
std::atomic<T*>提供的新操作是指针算术运算。这种基本的操作是由fetch_add()和fetch_sub()成员函数提供。

不要在锁定范围之外,向受保护的数据通过将其作为参数传递给用户所提供的函数的方式,传递指针和引用。一般情况下,编译器无法为std::atomic<UDT>生成无锁代码,所以它必须对所有的操作使用一个内部锁

有锁和无锁的并发设计

todo

七、C++模板问题 模板元编程 POD 类型萃取

template

  • 类的模板可以偏特化,函数的不可以,因为函数偏特化的功能可以通过重载来实现
  • 类的特化问题,偏特化等
  • 函数的模板
  • 类的模板问题

ref chromium //third_party/blink/renderer/platform/heap/heap.h

// Constructs an instance of T, which is a garbage collected type. This special
// version takes size which enables constructing inline objects.
template <typename T, typename... Args>
T* MakeGarbageCollected(AdditionalBytes additional_bytes, Args&&... args) {
  T* object = MakeGarbageCollectedTrait<T>::Call(additional_bytes,
                                                 std::forward<Args>(args)...);
  PostConstructionHookTrait<T>::Call(object);
  return object;
}

多参数问题,函数模板,完美转发,特化,类型萃取,MakeGarbageCollectedTrait ,GC类型萃取

template <typename T>
struct MakeGarbageCollectedTrait {
  template <typename... Args>
  static T* Call(Args&&... args) {
    static_assert(WTF::IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");
    static_assert(
        std::is_trivially_destructible<T>::value ||
            std::has_virtual_destructor<T>::value || std::is_final<T>::value ||
            internal::IsGarbageCollectedContainer<T>::value ||
            internal::HasFinalizeGarbageCollectedObject<T>::value,
        "Finalized GarbageCollected class should either have a virtual "
        "destructor or be marked as final");
    static_assert(!IsGarbageCollectedMixin<T>::value ||
                      sizeof(T) <= kLargeObjectSizeThreshold,
                  "GarbageCollectedMixin may not be a large object");
    void* memory = T::template AllocateObject<T>(sizeof(T));
    HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
    // Placement new as regular operator new() is deleted.
    T* object = ::new (memory) T(std::forward<Args>(args)...);
    header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
    return object;
  }

  template <typename... Args>
  static T* Call(AdditionalBytes additional_bytes, Args&&... args) {
    static_assert(WTF::IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");
    static_assert(
        std::is_trivially_destructible<T>::value ||
            std::has_virtual_destructor<T>::value || std::is_final<T>::value ||
            internal::IsGarbageCollectedContainer<T>::value ||
            internal::HasFinalizeGarbageCollectedObject<T>::value,
        "Finalized GarbageCollected class should either have a virtual "
        "destructor or be marked as final.");
    const size_t size = sizeof(T) + additional_bytes.value;
    if (IsGarbageCollectedMixin<T>::value) {
      // Ban large mixin so we can use PageFromObject() on them.
      CHECK_GE(kLargeObjectSizeThreshold, size)
          << "GarbageCollectedMixin may not be a large object";
    }
    void* memory = T::template AllocateObject<T>(size);
    HeapObjectHeader* header = HeapObjectHeader::FromPayload(memory);
    // Placement new as regular operator new() is deleted.
    T* object = ::new (memory) T(std::forward<Args>(args)...);
    header->MarkFullyConstructed<HeapObjectHeader::AccessMode::kAtomic>();
    return object;
  }
};

POD, RTTI问题

STL部分容器、算法的实现

gcc gdb使用等等

gcc 用法简介

  • 预处理
    gcc -E hello.c -o hello.i or 或 gcc -E test.c
  • 生成汇编
    ** gcc -S asmex.cpp -lstdc++ -std=c++11 -o asmex3.s
    ** gcc -s hello.c -o hello.s or ** gcc -s hello.i -o hello.s
  • 生成目标文件
    gcc -c hello.s -o hello.o or ** gcc -S hello.c -o hello.o
  • 链接目标文件
    gcc hello.o -o hello
    直接生成 gcc hello.cpp -lstdc++ -std=c++11 -o hello // 带参数编译 ./hello运行
    gcc hello.c
    多个文件 gcc hello1.c hello2.c -o hello

g++ -std=c++14 -g3 -pthread -o2 le007.cpp -o le07

  • 静态库和动态库的问题 todo

  • 多个文件以及大型程序的组织参见后文

gdb用法简介. lldb用法

  • 启动调试
  • 断点设置
  • 变量查看
  • 单步调试
  • 源码查看

字符问题 对齐问题

todo

跨平台设计问题

跨平台 -- OS
  • ifdef 宏定义
  • impl设计
  • 目录 命名等区分
跨平台 -- 底层芯片的设计区分

这部分大部分都是涉及到高性能的问题需要注意

  • 线程安全设计时 例如volitile atomic等涉及到内存屏障的问题部分芯片支持的情况不一样(大部分主流芯片都比较一致)
  • 涉及到L1(2,3)cache
  • 涉及到neon优化 和GPU计算高度相关的设计需要注意不同芯片支持的情况
  • 需要注意字符宽度,字符对齐 32位 64位(兼容32位)的区别
  • size_t的使用以及由来 数据总线宽度 和地址宽度的问题

七、 编译 链接过程 以及大型程序的组织 server ex

todo

设计模式

设计模式六大原则

总原则:开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。

1、单一职责原则

不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。

2、里氏替换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。

里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。

5、迪米特法则(最少知道原则)(Demeter Principle)

就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。

最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。

6、合成复用原则(Composite Reuse Principle)

原则是尽量首先使用合成/聚合的方式,而不是使用继承。

三大类 23钟设计模式

创建型模式

工厂模式 抽象工厂模式 build模式 单例模式 原型模式

工厂模式 & 抽象工厂模式
  • 定义Product
class Product {
    public:
        Product() {}
};
class ConcreteProduct: public Product {
     public:
            ConcreteProduct() {}
}
  • 定义工厂
class Factory {
    public:
          ////////
        Product* FactoryMethod()  {
            return new Product();
        }
       // or 
             Product* FactoryMethod2(char * productName)  {
            if (strcmp(productName, "xxxxxx")) {
                return new ConcreteProduct();   
            // todo else if
        }
    private:
      Product * product;
}
class ConcreteFactory : public Factory {
   public: 
           Product * FactoryMethod () {
          return new ConcreteProduct();
       }
}
单例模式

danli

class Singleton { 
     public: 
          Singleton()  { 
            cout<<"Singleton default construct"<<endl;
            };
            
        ~ Singleton()  { 
            cout<<"Singleton default construct"<<endl;
            };
        
        void SingletonPrint() {
            cout<< " this thread is" << this <<endl;
        }
        
        //  没有线程安全
        /*  static Singleton* getInstance() {
                 if (_instance == NULL) {
                    _instance = new Singleton();
                    }   
                    return _instance;
               }*/

       //  线程安全
         static Singleton* getInstance() {
                  if (_instance == NULL)   {
                 std::unique_lock<mutex> lock(mu); // 加锁
                if (_instance == NULL)  {
                      _instance = new  Singleton();
                 }
            }
       
                    return _instance;
               }
    private:
      static Singleton * _instance;

     // 考虑线程安全
          static mutex mu;
};
  • 初始化static变量
Singleton *  Singleton::_instance = nullptr;
 mutex Singleton::mu;

call_once方式


class Singleton{
public:
  static Singleton& getInstance(){
    std::call_once(initInstanceFlag, &Singleton::initSingleton);
    // volatile int dummy{};
    return *instance;
  }
private:
  Singleton() = default;
  ~Singleton() = default;
  Singleton(const MySingleton&) = delete;
  Singleton& operator= (const MySingleton&) = delete;
  static Singleton* instance;
  static std::once_flag initInstanceFlag;
  static void initSingleton() {
    instance = new Singleton;
  }
};

Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::initInstanceFlag;
  • 实际调用示例
        
void print() {
    //this_thread::sleep_for(std::chrono::milliseconds(1000));
    Singleton::getInstance()->SingletonPrint();
}



int  main() {
    thread tA(print);
    thread tB(print);
    tA.join();
    tB.join();
    
    return 0;
}
Build模式

class Maze {
    public:
        Maze() { cout<<"Maze construct function<<endl";}
};

class MazeBuilder {
    public:
        virtual void BuildMaze()  { }
        virtual void BuildRoom(int room) {cout<<"room = "<<room<<endl; }
        virtual void BuildDoor(int roomSrc, int roomDest) {cout<<"roomSrc = "<<roomSrc<<endl;  }
    protected:
        MazeBuilder () { cout << "MazeBuilder construct entering..."<<endl;}
};

class ConcreteMazeBuilder : public MazeBuilder {
    public:
        ConcreteMazeBuilder( ) { cout << "ConcreteMazeBuilder construct entering..."<<endl;}
        
        void BuildRoom() {}
        
    private:
        Maze * maze;
};

class Director {
    public:
        Director(MazeBuilder * _builder) {
            builder = _builder;
        }
        
        void construct() {
            builder->BuildRoom(10);
            builder->BuildDoor(10,11);
        }
    private:
        MazeBuilder * builder;
};

proto模式

class Proto {
    public:
        //virtual Proto() = delete;
        virtual ~Proto() {}
        virtual Proto* clone() = 0;
        virtual void print() = 0;
};

class ConCreteProto : public Proto{
    public:
        ConCreteProto() {};
        
        ConCreteProto(int _val, const string & _valStr) {
            val = _val;
            valStr = _valStr;
        }
        
         virtual ~ConCreteProto( ) {}
         
        virtual Proto* clone() {
            ConCreteProto *p = new ConCreteProto();
            p->val = val;
            p->valStr = valStr;
            return p;
        }
        
        void print() {
            cout<<"val = "<<val<<endl;
            cout<<"valString = "<<valStr<<endl;
        }
        
    private:
        int val;
        string valStr;
};


结构型模式

Bridge Adapter 装饰 组合 享元模式 facade Proxy模式

适配器模式 Adapter

class Shape {
    public: 
        virtual void BoundingBox()  = 0;
    
};

class TextView {
    public:
        int getExtent() { return 1;}
    
};

// 两种不同adapter方式 --1
class TextShape:public Shape {
    public:
        TextShape(TextView * _view) : view(_view) {
            
        }
        void BoundingBox()  {view->getExtent();}
        
    private:
        TextView * view;
};

// 两种不同adapter方式 --2
class TextShape : public Shape, private TextView {
    public:
        TextShape()  {
            
        }
        void BoundingBox()  { getExtent()}
        
    
};
桥模式 Bridge

class WindowImp {
    public:
        virtual void impDrawBound() = 0;
};

class Window {
    public:
        void drawBound() {
            imp->impDrawBound();
        }
     private: 
      WindowImp * imp;
};

class XWindowImp : public WindowImp {
    public:
        void impDrawBound() {
            cout<< "imp draw bound"<<endl;
        }
};
Proxy模式

class Graphic {
    public: 
        virtual void Draw() = 0;
        virtual void GetExtend() = 0;
};

class Image : public Graphic {
    public: 
        void Draw() {} 
        void GetExtend() {}
        Image * loadImage() { Image * m = new Image(); return m;}
};

class ImageProxy : public Graphic  {
    public:
        void Draw() {
            if(image == nullptr) {
                image = loadImage();
            }
            image->Draw();
        }
        void GetExtend() {
            
        }
    private:
        Image * image;
}
Flyweight享元模式

运用共享技术有效地支持大量细粒度的对象


class Flyweight {
    public:
        virtual void draw() = 0;
};

class ConcreteFlyweight {
    public:
        void draw() {
            cout<<"drawing"<<endl;
        }
        
        friend ostream& operator<<(ostream& os, ConcreteFlyweight& obj) {
        return os <<
            obj.getVal() << "(id=" << obj.val << ") " ;
    }
    
    int getVal() {return val;}

    private:
        int val;
};

class FlyweightContext {
    public:
        Flyweight * CreateFlyweight(int val) { return nullptr;}
    private:
        map<int,int> flyweightMap;
};

装饰模式

动态地给一个对象添加一些额外的职责


class Component {
    public: 
        virtual void draw() = 0;
};

class ConcreteComponent : public Component {
    public:
    void draw () {
        cout<< "ConcreteComponent draw "<<endl;
    }
};

class Decorate : public Component {
    public:
         Decorate(Component * _component) : component(_component) {}
        Decorate() = delete;
        void draw() {
            component->draw();
        }
        
    protected:
        Component * component;
};

class XDecorate : public Decorate {
    public:
        XDecorate(Component * _component) : Decorate(_component) {}
            // 
        void draw() {
            Decorate::draw();
            addOperation();
        }
        
    private:
        void addOperation() { cout<<"addOperation"<<endl; }
};

C++初始化列表的注意事项。

In a non-delegating constructor, initialization proceeds in the following order:

— First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.

— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

— Finally, the compound-statement of the constructor body is executed.

组合


class Component {
    public:
        virtual void operation() = 0;
};

class Leaf : public Component {
    public:
        void operation ()  {
            cout<<"Leaf operation"<<endl;
        }
};

class Leaf2 : public Component {
    public:
        void operation ()  {
            cout<<"Leaf2 operation"<<endl;
        }
};

class Group : public Component {
    public:
        void operation ()  {
            for(auto child:children) {
                child->operation();
            }
        }
        
        void add(Component * _component) {
            children.push_back(_component);
        }
        
        void remove(Component * _component) {
            
        }
        
    private:
        vector<Component*> children;
};

facade

行为模式

模板模式
class Game {    // 定义基础游戏
    public: 
     explicit Game(uint32_t players): m_no_of_players(players) {}
    void run() {
        start();
        while (!have_winner())
            take_turn();
        cout << "Player " << get_winner() << " wins.\n";
    }
protected:
    virtual void start() = 0;
    virtual bool have_winner() = 0;
    virtual void take_turn() = 0;
    virtual uint32_t get_winner() = 0;
    uint32_t m_current_player{0};
    uint32_t m_no_of_players{0};
};

class Chess : public Game {   // 定义具体游戏规则
    public:
    explicit Chess(): Game {2} {}
protected:
    void start() {
        cout << "Starting chess with " << m_no_of_players << " players\n";
    }
    bool have_winner() { return m_turns == m_max_turns; }
    void take_turn() {
        cout << "Turn " << m_turns << " taken by player " << m_current_player << "\n";
        m_turns++;
        m_current_player = (m_current_player + 1) % m_no_of_players;
    }
    uint32_t get_winner() { return m_current_player; }
    
private:
    uint32_t m_turns{0}, m_max_turns{4};
};
策略模式

策略模式 可以为client提供一系列不同的实现方式


class Compositor {
    public:
        void strategy() = 0;
};

class XCompositor {
    public:
        void strategy() {
            cout<<"XCompositor strategy"
        }
};

class WCompositor {
    public:
        void strategy(int v) {  // depends on v
            cout<<"WCompositor strategy"
        }
};

class Composition {
    public:
        void SetStrategy(int strategyEnum) {
           switch(strategyEnum) {
                compositor = new WCompositor; 
                break;
        }
        void DoStrategy() {
            compositor->strategy();
        }
    private:
        Compositor * compositor;
}
状态模式
  • Classic

class StateContext;

class State {
    public:
        virtual void open(StateContext * context) = 0;
        virtual void send(StateContext * context) = 0;
        virtual void close(StateContext * context) = 0;
    protected:
        void changeState(StateContext * context, State *state);
};


class StateContext {
    public:
        void open() {
            state->open(this);
        }
        void send() {
            state->send(this);
        }
        void close() {
            state->close(this);
        }
        

        friend class State;
        
        void changeState(State * _state) {
            state = _state;
        }
    private:
        State * state;
};

class XState : public State {
    public:
        static State * getInstance() {
            return new XState();
        }
      void open(StateContext * context) {
        cout<<"XState open"<<endl;
      }
        void send(StateContext * context) {
            cout<<"XState send"<<endl;
        }
        void close(StateContext * context) {
            cout<<"XState close"<<endl;
        }
        
    private: 
        friend class StateContext;
        
        void changeState(StateContext * context, State *state) {
            context->changeState(state);
        }
    
};

todo modern C++ design pattern

观察者模式

class Observer {
    public:
        virtual void update() = 0;
};


class Subject {
    public:
        void doSub() {}
        void notify() {
            for(auto observer:observers) {
                observer->update();
            }
        }
        void attach(Observer * ob) {
            observers.push_back(ob);
        }
    private:
        list<Observer*>  observers;
};


class XObserver : public Observer {
    public:
        void update() {
            cout<<"XObserver update"<<endl;
        }
};
备忘录memento
中介模式
command
visitor
职责链
迭代
interprate

Modern Design Patterns

Type Erasure
CRTP
// CRTP example
  template<typename T>
  class Base {
    public:
        void show() const {
            static_cast<const T*>(this)->show();
        }
        
         Base<T> operator++() {
            static_cast< T*>(this)->operator++();
        }
  };
  
  class Derive : public Base<Derive> {
    public:
        Derive() : val(0) {}
        void show() const {
            cout<<"derive class object val = "<<val<<endl;
        }
        
        const Derive operator++() {
        ++(this->val);
        return *this;
    }
        
    private:
        int val;
  };

example

    Derive d;
    Base<Derive> *b = &d;
    b->show();
    ++(*b);
    b->show();
    
Expression Templates
Policy Based Design

面向对象的内存布局 , 引用折叠

各类继承方式的内存布局情况
一般继承,virtual继承,菱形继承,等等这些情况的内存布局,以及涉及到static成员的内存布局以及常见使用示例。

malloc free算法,size_t的由来, 系统启动,,,Linux和windows应用程序的构造区别等等

OS有关的问题 CPU访问内存, MMU内存管理单元 ,段页式内存管理

linux常用命令

编译原理的有关问题

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容