【问题标题】:CreateEventW unexpectedly failsCreateEventW 意外失败
【发布时间】:2016-01-08 18:20:12
【问题描述】:

如果我这样写一个简单的代码:

int main(int argc, char* argv[])
{
    HANDLE  hEvent = CreateEventW( NULL, FALSE, FALSE, L"EVENTTEST" );
    if (hEvent==NULL){
            cout<<"Error "<<GetLastError();
    }
    else{
            cout<<"Success";
    }

    getch();
    return 0;
}

代码运行并显示成功消息,但如果我在 main 上方的一般范围内添加一些声明(这里我只通过声明 bool 变量添加一行代码)函数 CreateEvenetW 失败,错误代码为 998。 如果我使用 CreateEvent 而不是 CreateEventW 就不会出现问题。但是我想知道当我添加这样一个简单的变量声明时 CreateEventW 会发生什么:

bool x=true;
int main(int argc, char* argv[])
{
    HANDLE  hEvent = CreateEventW( NULL, FALSE, FALSE, L"EVENTTEST" );
    if (hEvent==NULL){
            cout<<"Error "<<GetLastError();
    }
    else{
            cout<<"Success";
    }

    getch();
    return 0;
}

这些奇怪的意外错误让我担心使用一些 winapi 函数。

我应该提到代码是用 Borland c++ 6 编译的

编辑:如果我在没有初始化的情况下声明变量(如:bool x),则不会发生错误。此外,此问题仅发生在某些数据类型上。我检查了类型(int、double)并且程序运行时显示“成功”消息。但是类型 (char,bool) 在初始化时会导致错误。

【问题讨论】:

  • 返回值记录在here,但998不在其中(998是ERROR_NOACCESS)。尽管仅仅因为 bool x = true 而使函数的行为有所不同,这听起来更像是 2002 年的编译器的问题 en.wikipedia.org/wiki/C%2B%2BBuilder
  • @herohuyongtao 我渴望知道这与使用硬 Unicode 名称直接调用 CreateEvent 的 Unicode 版本有什么关系。请告诉PLZ。
  • GetLastError 返回 998,从这里 msdn.microsoft.com/en-us/library/windows/desktop/… 你可以看到它说:对内存位置的访问无效。
  • 您应该将GetLastError() 的值放入一个局部变量中,然后输出:DWORD e = GetLastError(); cout &lt;&lt; "Error " &lt;&lt; e &lt;&lt; endl;。如果您不这样做,可能会在调用 GetLastError() 之前运行代码,从而覆盖您的实际错误代码。
  • @user2808671 - 很抱歉看到您遇到问题。我知道您提供的代码片段没有任何内容可能导致 CreateEvent 像那样失败。我怀疑是 Borland 工具,但我不能肯定。 Visual C++ 和 Visual Studio 可免费下载。

标签: c++ winapi


【解决方案1】:

在 Windows 程序中出现错误 998 表示存在非常严重的问题。当内核本身可以判断进程堆已损坏时,您会得到这个。当程序未处于无法安全生成 AV 异常的状态时,通常会生成它,而不是由于堆损坏而导致的正常访问冲突。这首先发生在 Windows 加载程序忙于加载 DLL 并运行 DllMain() 入口点时。您的调试器可能会显示第一次机会异常通知。无论如何希望。

当然,您发布的代码永远不会重现此错误,该问题是由其他代码引起的。在 DLL 中(很可能)或在进入 main() 函数之前运行的初始化代码中。破坏堆当然是一个标准的 C++ 问题。您可能会从Application Verifier 工具中获得帮助。祝你好运。

【讨论】:

  • 正如我所说,这个简单的代码单独运行并失败。当然,这是一个更大项目的一小部分,但这段代码有我谈到的问题。这段代码之前的只是一些包含定义而已。
  • 避免大喊大叫。我从来没有说过是你的代码有问题。永远不会缺少将 DLL 注入进程的铲件。我给了你一个非常具体的故障排除建议,AppVerifier 告诉你什么?
  • 我没有喊哥们。 AppVerifier 日志报告无错误和无警告
【解决方案2】:

免责声明:这是在黑暗中猜测。

由于您正在创建一个命名事件(“EVENTTEST”),其他一些进程(可能仍在运行)之前可能已经使用一组不同的权限创建了该事件。也许一个实例在具有管理员权限的命令 shell 中运行,而失败的实例没有?

换句话说,这是命名内核句柄的某种安全/ACL 问题。

另一个猜测:“x=true”线只是红鲱鱼,问题在某种程度上取决于时间。

您可以检查事件日志(控制面板->管理工具->事件查看器)。然后检查“Windows 日志”文件夹下的应用程序、系统和安全日志。它可能会揭示一些东西......

否则,请重新启动并重试。除非您需要事件句柄跨不同进程工作,否则只需将“EVENTTEST”替换为 NULL,让同一进程中的线程共享句柄即可。

【讨论】:

  • 感谢您的回复。但是我在两台不同的计算机上多次检查了这段代码,结果相同。每当我删除该行时,再次添加该行时,该函数就会成功...根据您提到的内容,我将最后一个参数设置为 NULL 并且错误消失了。但我需要事件有一个名称。因为如果另一个程序实例运行,那么通过检查这个事件它必须关闭。我不希望我的程序执行多个实例。无论如何我也会检查系统日志。
  • 我查看了 Windows 日志,但没有发现任何与问题相关的内容
猜你喜欢
  • 2013-09-18
  • 1970-01-01
  • 2020-06-30
  • 2021-12-04
  • 2018-01-02
  • 2017-09-20
  • 2013-05-25
  • 2017-07-23
  • 2016-06-22
相关资源
最近更新 更多