【问题标题】:How could just loading a dll lead to 100 CPU load in my main application?在我的主应用程序中加载一个 dll 怎么会导致 100 个 CPU 负载?
【发布时间】:2020-07-28 14:42:23
【问题描述】:

我有一个完美运行的程序,它连接到摄像机(IDS uEye 摄像机)并不断从中抓取帧并显示它们。

但是,在连接到相机之前加载特定的 dll 时,程序会以 100% 的 CPU 负载运行。如果我在连接到相机后加载 dll ,程序运行正常。

int main()
{
    INT nRet = IS_NO_SUCCESS;
    // init camera (open next available camera)
    m_hCam = (HIDS)0;

    // (A) Uncomment this for 100% CPU load:
    // HMODULE handle = LoadLibrary(L"myInnocentDll.dll");

    // This is the call to the 3rdparty camera vendor's library:
    nRet = is_InitCamera(&m_hCam, 0);    

    // (B) Uncomment this instead of (A) and the CPU load won't change
    // HMODULE handle = LoadLibrary(L"myInnocentDll.dll");

    if (nRet == IS_SUCCESS)
    {
        /*
         * Please note: I have removed all lines which are not necessary for the exploit.
         * Therefore this is NOT a full example of how to properly initialize an IDS camera!
         */
        is_GetSensorInfo(m_hCam, &m_sInfo);

        GetMaxImageSize(m_hCam, &m_s32ImageWidth, &m_s32ImageHeight);

        m_nColorMode = IS_CM_BGR8_PACKED;// IS_CM_BGRA8_PACKED;
        m_nBitsPerPixel = 24; // 32;
        nRet |= is_SetColorMode(m_hCam, m_nColorMode);

        // allocate image memory.
        if (is_AllocImageMem(m_hCam, m_s32ImageWidth, m_s32ImageHeight, m_nBitsPerPixel, &m_pcImageMemory, &m_lMemoryId) != IS_SUCCESS)
        {
            return 1;
        }
        else
        {
            is_SetImageMem(m_hCam, m_pcImageMemory, m_lMemoryId);
        }
    }
    else
    {
        return 1;
    }

    std::thread([&]() {
        while (true) {
            is_FreezeVideo(m_hCam, IS_WAIT);
            /*
             * Usually, the image memory would now be grabbed via is_GetImageMem().
             * but as it is not needed for the exploit, I removed it as well
             */
        }
        }).detach();

    cv::waitKey(0);
}

独立于实际使用的相机驱动程序,加载 dll 会以何种方式改变其性能,占用所有可用 CPU 内核的 100%?使用 Visual Studio 诊断工具时,多余的 CPU 时间归因于“[External Call] SwitchToThread”而不是 myInnocentDll。

仅加载 dll 而不初始化相机不会导致 100% 的 CPU 负载。

我首先想到 myInnocentDll.dll 中的一些静态初始化程序配置一些线程行为,但我没有找到任何指向这个方向的东西。在myInnocentDll.dll的代码中我应该寻找哪些方面?

【问题讨论】:

  • SwitchToThread 使用的 100% cpu 很可能来自自旋锁。您是否在 DllMain 中为线程/进程附加事件做任何事情? Here are some things that will cause problems。静态初始化也可以调用相同的。如果没有,我会咬紧牙关,当它在SwitchToThread 时进入该过程,然后走出去寻找正在做的事情。您必须在汇编中进行调试,但了解正在发生的事情并不难。
  • @TainToTain 感谢您的浏览!我的代码中不存在 DllMain。确实可能是一些静态初始化,但是我对如何在这里找到针头一无所知。不幸的是,在发布模式下,附加到堆栈只会显示“外部代码”。并且在调试模式下,问题不会出现
  • myInnocentDll.dll 将有一个DllMain。该函数中有什么代码?
  • 其他一些事情要检查myInnocentDll:你在使用COM吗?是否有任何静态初始化对象的 ctor 调用 STL 或 CRT 方法?基本上任何可能在静态初始化程序中加载另一个库的东西都是不好的,并且可能导致死锁。我怀疑会有。对于 Visual Studio 程序集级调试,您需要 enable "address-level debugging"
  • 您可以使用 Process Explorer 并检查线程堆栈以及它们对 CPU 时间的作用吗? docs.microsoft.com/en-us/sysinternals/downloads/…

标签: c++ dll c++17 ids ueye


【解决方案1】:

经过大量挖掘,我找到了答案,它本身既简单又令人沮丧:

这是微软对OpenMP的支持不佳。当我在项目中禁用 OpenMP 时,相机驱动程序运行良好。

原因似乎是 Microsoft 编译器使用 OpenMP 并忙于等待,也可以手动配置 OMP_WAIT_POLICY,但由于我不依赖 OpenMP,因此禁用对我来说是最简单的解决方案。

我仍然不明白为什么 CPU 只在使用相机时升高,而不是在运行我的解决方案的其余部分时升高,即使相机库是预先构建的并且我对 OpenMP 编译的禁用/启用不能有任何对其产生影响。而且我也不明白为什么他们费心为 VS2010 做一个修补程序,但我正在使用的 VS2019 却没有真正的修补程序。但问题被避免了。

【讨论】:

    【解决方案2】:

    您可以在 IDS 相机管理器中禁用 CPU 空闲状态,然后将 windows 能源计划中的最小 CPU 负载设置为 100%

    我认为这里值得一提,即使你已经解决了你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多