【问题标题】:Can't open existing semaphore from another process C++无法从另一个进程 C++ 打开现有信号量
【发布时间】:2022-01-21 19:26:59
【问题描述】:

我正在尝试从另一个进程获取现有信号量。要创建我使用的信号量:

Semaphore(std::string name, int startState) {
    name = "Global\\" + name;
    Sem = OpenSemaphore(SYNCHRONIZE | SEMAPHORE_MODIFY_STATE, true, (LPCWSTR)name.c_str());
    int s = (startState > 0);
    if (Sem == NULL) {
        Sem = CreateSemaphore(NULL, s, 1, (LPCWSTR)name.c_str());
    }
}

在第一个进程中正确创建了信号量。 GetLastError() 返回 0。在第二个过程中,OpenSemaphore 返回 NULL。 GetLastError() 返回 2。 我试图只通过“名称”来获取信号量 - 没有“全局”,但它得到了相同的结果。请帮忙)

【问题讨论】:

    标签: c++ multithreading winapi semaphore


    【解决方案1】:

    @SomeProgrammerDude's answer 解释了您看到的错误的原因(字符编码不匹配)。

    我只想指出,在解决了这个问题之后,您的代码中仍然存在竞争条件。

    如果你想打开一个现有的信号量(或任何其他类型的命名内核对象),如果它不存在就创建它,那么不要浪费时间打开它,只需无条件地创建它,例如:

    Semaphore(std::string name, int startState) {
        name = "Global\\" + name;
        int s = (startState > 0);
        Sem = CreateSemaphoreA(NULL, s, 1, name.c_str());
    }
    

    如果对象已经存在,你会得到一个现有对象的句柄,输入参数将被忽略。否则,您将获得使用您的参数初始化的新对象的句柄。 GetLastError() 可用于告诉您该对象是否已经存在或是否重新创建(如果需要)。

    【讨论】:

      【解决方案2】:

      如果您觉得需要使用 C 风格的转换(例如在 (LPCWSTR)name.c_str() 中),您应该将其视为您做错了什么的迹象。

      就像你在这里做的:std::string 是一个 narrow 字符(即char)字符串,而你使用 wide 字符(wchar_t) 函数。这意味着名称不会是您所期望的。

      如果您继续使用std::string,您必须使用“ANSI”函数(例如CreateSemaphoreA)。否则切换到使用宽字符的std::wstring

      【讨论】:

      • 你是最棒的!这是第一种情况,我坚持使用 wchars 和 chars。非常感谢!)
      • @kepich 从不​​使用类型转换来消除编译器错误,除非您真的知道自己在做什么。如果您删除了类型转换,编译将由于类型不匹配而失败。解决这些错误的原因,不要只是掩盖它们。
      猜你喜欢
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-10
      • 2016-08-17
      • 2016-09-01
      • 2016-04-22
      • 1970-01-01
      相关资源
      最近更新 更多