简体   繁体   English

c,共享库中的c ++内存

[英]c, c++ memory in shared libraries

I am uncertain how static global memory is managed in DLL's and shared objects. 我不确定如何在DLL和共享对象中管理静态全局内存。 I do not know if each handles it in the same way or different on different platforms. 我不知道每个人在不同平台上是以相同的方式还是以不同的方式处理它。

Consider you have a library of classes, one of those classes is a mutex class and other classes in the library will use that mutex. 考虑您有一个类库,其中一个类是互斥锁类,并且库中的其他类将使用该互斥锁。 What is the best or safest way to allocate a mutex in the library? 在库中分配互斥体的最佳或最安全的方法是什么? I can see a couple options: 我可以看到几个选择:

  1. Make the mutex private in the class. 在课程中将互斥锁设为私有。 This I can't see working because the mutex life would only be valid within the lifetime of the object. 我看不到这起作用,因为互斥锁寿命仅在对象的生存期内有效。 Maybe making the object a singleton and initializing it when the library is loaded (with dllattach or attribute ((constructor))) would work, I am not sure. 我不确定是否可以使对象成为单例并在加载库时初始化它(使用dllattach或属性 ((constructor)))。

  2. Allocate the mutex outside of the class in static global space of the library. 在类的外部在库的静态全局空间中分配互斥量。 I think this would be the best option but what exactly happens when the DLL is loaded? 我认为这将是最好的选择,但是在加载DLL时究竟会发生什么? If I made an object static and global in a library when does it get allocated, where in the program does it get allocated? 如果我在库中将对象设为静态和全局对象,什么时候分配它,在程序中哪里分配它? What happens if the library is loaded during runtime as opposed to when the program starts? 如果在运行时而不是程序启动时加载库,会发生什么情况?

Any information about this is greatly appreciated! 非常感谢有关此的任何信息!

The way memory is managed in shared images depends on specific platforms, and DLLs are specific to Microsoft Windows. 在共享映像中管理内存的方式取决于特定的平台,并且DLL特定于Microsoft Windows。

Generally, you should always avoid using global/shared static variables , as they may introduce serious problems or bugs which are hard to identify or resolve. 通常, 您应该始终避免使用全局/共享静态变量 ,因为它们可能会引入严重的问题或难以识别或解决的错误。 Even singleton classes may cause several issues in C++ , specially in libraries or multi-threaded applications. 甚至单例类也可能在C ++中引起一些问题 ,尤其是在库或多线程应用程序中。 (And generally, using singletons are not considered good even in higher level languages.) (通常,即使在高级语言中,使用单例也不被认为是好的 。)

For guarding against mutual exclusion race conditions, the best option would be to use a scoped lock class implemented using RAII technique , alongside the shared_ptr smart pointer , which automates memory allocation and de-allocation. 为了防止相互排斥的竞争情况,最好的选择是使用通过RAII技术实现的范围锁类,以及shared_ptr 智能指针 ,该指针自动执行内存分配和取消分配。

The below code illustrates implementing Mutex by using Windows API and the above techniques (as well as Pimpl idiom ): 下面的代码说明了如何使用Windows API和上述技术(以及Pimpl习惯用法 )实现Mutex

// Mutex.h
#pragma once
#include <memory>

class Mutex
{
public:
    typedef unsigned long milliseconds;

    Mutex();
    ~Mutex();

    void Lock();
    void Unlock();
    bool TryLock();
    bool TimedLock(milliseconds ms);

private:
    struct private_data;
    std::shared_ptr<private_data> data;
    // Actual data is hold in private_data struct which is non-accessible.
    // We only hold a "copyable handle" to it through the shared_ptr, which 
    // prevents copying this "actual data" object by, say, assignment operators.
    // So, private_data's destructor automatically gets called only when the last
    // Mutex object leaves its scope.
};


// Mutex.cpp
#include "Mutex.h"
#include <windows.h>

struct Mutex::private_data
{
    HANDLE hMutex;

    private_data()
    {
        hMutex = CreateMutex(NULL, FALSE, NULL);
    }

    ~private_data()
    {
        // Unlock(); ?? :/
        CloseHandle(hMutex);
    }
};

Mutex::Mutex()
    : data (new private_data())
{ }

Mutex::~Mutex()
{ }

void Mutex::Lock()
{
    DWORD ret = WaitForSingleObject(data->hMutex, INFINITE);
    ASSERT(ret == WAIT_OBJECT_0);
}

void Mutex::Unlock()
{
    ReleaseMutex(data->hMutex);
}

bool Mutex::TryLock()
{
    DWORD ret = WaitForSingleObject(data->hMutex, 0);

    ASSERT(ret != WAIT_ABANDONED);
    ASSERT(ret != WAIT_FAILED);

    return ret != WAIT_TIMEOUT;
}

bool Mutex::TimedLock(milliseconds ms)
{
    DWORD ret = WaitForSingleObject(data->hMutex, static_cast<DWORD>(ms));

    ASSERT(ret != WAIT_ABANDONED);
    ASSERT(ret != WAIT_FAILED);

    return ret != WAIT_TIMEOUT;
}


// ScopedLock.h
#pragma once
#include "Mutex.h"

class ScopedLock
{
private:
    Mutex& m_mutex;

    ScopedLock(ScopedLock const&);             // disable copy constructor
    ScopedLock& operator= (ScopedLock const&); // disable assignment operator

public:
    ScopedLock(Mutex& mutex)
        : m_mutex(mutex)
    { m_mutex.Lock(); }

    ~ScopedLock()
    { m_mutex.Unlock(); }
};

Sample usage: 用法示例:

Mutex m1;
MyClass1 o1;
MyClass2 o2;
...

{
    ScopedLock lock(m1);

    // thread-safe operations
    o1.Decrease();
    o2.Increase();

} // lock is released automatically here upon leaving scope

// non-thread-safe operations
o1.Decrease();
o2.Increase();


While the above code will give you the basic idea, even the better option is to use high-quality C++ libraries like boost , which have mutex , scoped_lock and many other classes already available. 尽管上面的代码将为您提供基本的思想,但更好的选择是使用诸如boost的高质量C ++库,该库具有mutexscoped_lock和许多其他可用的类。 (And fortunately C++11 makes complete coverage of synchronization classes, freeing you from having to use boost libraries.) (幸运的是,C ++ 11完全覆盖了同步类,使您不必使用boost库。)

UPDATE: 更新:
I suggest you to search for topics about automatic garbage collection in C++ as well as the RAII technique. 我建议您搜索有关C ++自动垃圾收集以及RAII技术的主题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM