【问题标题】:What is wrong with this tiny piece of mutex code?这段小互斥代码有什么问题?
【发布时间】:2008-11-20 14:56:31
【问题描述】:
// A Mutex allows threads mutually exclusive access to a resource.
//-----------------------------------------------------------------------

class Mutex
{
private:
    CRITICAL_SECTION m_mutex;

public:
     Mutex() { InitializeCriticalSection(&m_mutex); }
    ~Mutex() { DeleteCriticalSection(&m_mutex);     }

    void acquire() { EnterCriticalSection(&m_mutex); }
    void release() { LeaveCriticalSection(&m_mutex); }
};

使用Entrek Codesnitch软件调试测试内存泄漏等,报如下错误:

InitializeCriticalSection Error: lpCriticalSection (0x000387d4) points to an invalid 
  memory location (0x00018984) Mutex::Mutex in lockmutex.h, line 29

也许我所有的不眠之夜终于来到了我身边。但我不明白它到底在抱怨什么。有什么想法吗?

【问题讨论】:

  • 您使用的是新展示位置吗?如果构造函数得到一个无效的指针,你将无法在 Mutex 类中修复它。
  • 你在这里选择的命名很糟糕,因为这真的是不是互斥体。 Mutex 是通过调用 CreateMutex 创建的,它是一个同步对象,可以在系统中的所有进程中命名和使用。 CRITICAL_SECTION 仅在创建过程中有效。
  • 语义。除了基于 Win32 的操作系统之外,大多数操作系统都将这些称为“轻量级互斥体”而不是关键部分;关键部分更正确地指的是您使用 CRITICAL_SECTION 而不是构造本身保护的操作。
  • 语义学,是的,但是如果您在 Windows 系统上工作(他显然是)并且您必须与其他开发人员交流您正在做什么,然后您说“我创建了一个互斥锁保护这个代码部分”他们会自动推断什么?互斥体,而不是关键部分。

标签: c++ mutex critical-section


【解决方案1】:

CodeSnitch 显然不够聪明,无法知道 InitializeCriticalSection() 期望处理包含未初始化指针的结构。

从 CodeSnitch 的角度来考虑。你在做什么和这个有什么区别:

struct Customer {
    char * name;
};

extern void greetCustomer(Customer* c);

class CheckoutLine {
  private:
    Customer m_customer;
  public CheckoutLine() {
    greetCustomer(&m_customer);
  }
};

这对人类的眼睛来说看起来更可疑,因为我们推断 greetCustomer 可能会依赖于 m_customer 被初始化,但显然不是。但在语义上,这与您的代码完全相同。

可能值得向 Entrek 提交错误; InitializeCriticalSection() 是“结构在传递给函数之前应该初始化”规则的一个合理例外。

【讨论】:

    【解决方案2】:

    我敢打赌,你可以用 ::memset ( & m_mutex, 0, sizeof ( m_mutex ) ) 伪造告密者;在调用它之前。

    【讨论】:

      【解决方案3】:

      我看不出你的班级有什么问题定义。但是它在哪里使用?一个特定的实例仍然可能被错误地使用。

      CRITICAL_SECTION 的 Win32 定义包括指向“struct _RTL_CRITICAL_SECTION *”的指针。操作系统可能巧妙地处理了这个结构,以混淆工具的方式。

      【讨论】:

        猜你喜欢
        • 2015-04-25
        • 2018-09-09
        相关资源
        最近更新 更多