仅仅加载一个dll为什么会导致我的主程序的CPU利用率达到100%?

4
我有一个完全正常运行的程序,它连接到一个视频摄像头(一台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的代码中寻找哪些方面呢?


3
SwitchToThread 使用 100% 的 CPU 很可能是由于自旋锁导致的。在 DllMain 中是否执行了与线程/进程附加事件相关的操作?这里有一些可能会引起问题的操作。静态初始化也可能会触发相同的情况。如果没有,请直接进入进程并在 SwitchToThread 中中断,然后跳出来查找是什么导致了这个情况。虽然需要在汇编语言中进行调试,但了解正在发生的事情并不是非常困难。 - TainToTain
@TainToTain 感谢您的关注!我的代码中没有DllMain。确实可能是一些静态初始化问题,但我不知道如何找到这个问题。不幸的是,在Release模式下,附加到堆栈只显示“外部代码”。在调试模式下,问题并未出现。 - PhilLab
myInnocentDll.dll 将有一个 DllMain。那个函数中有什么代码? - 1201ProgramAlarm
你能使用“Process Explorer”来检查线程堆栈以及它们如何利用CPU时间吗?https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer - chakaz
myInnocentDll.dll 中尝试使用任何静态初始化程序线程同样有可能出现问题。另一个可能的选项是使用Intel Inspector检查供应商库的竞争条件行为。最后,使用Dependency Walker检查您和供应商库各自引入的符号和其他库,您可能会遇到冲突! - Ext3h
显示剩余2条评论
2个回答

0

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

我认为即使您已经解决了问题,这也值得在此提及。


0
经过大量挖掘,我找到了答案,它既让人沮丧的简单又令人沮丧:
这是由于Microsoft对OpenMP支持不佳。当我在我的项目中禁用OpenMP时,摄像头驱动程序就可以正常运行了。
原因似乎是Microsoft编译器使用带有忙等待的OpenMP,也可以手动配置OMP_WAIT_POLICY,但由于我并不依赖于OpenMP,因此禁用它是我最简单的解决方案。

我仍然不明白为什么CPU只在使用相机时才会升高,而在运行我的解决方案的其余部分时却没有升高,尽管相机库是预构建的,我的禁用/启用OpenMP编译也不可能对其产生任何影响。我也不明白为什么他们为VS2010制作了热修复补丁,但截至VS2019,我正在使用的版本,却没有真正的修复。但问题已经被避免了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接