【发布时间】:2022-01-30 16:35:10
【问题描述】:
主应用程序在 Windows 服务中运行,该进程启动其他 c++ 控制台进程,但所有控制台模式都被隐藏,即父进程是 Windows 服务,子进程是非控制台应用程序。
在客户系统 windows server 2016 上调用 _popen() 期间观察到系统的分页池内存正在增加。该应用程序在我们的实验室系统相同的操作系统上运行干净。
从 Windows 性能工具 xperf,捕获日志并检查调用堆栈。 附上图片供参考。
void CMachine::GetJavaVersion()
{
m_stJavaVersion.m_strName = " Java version";
CPUChar strVersion[64] = { 0 };
BOOL bFound = CheckJREVersion(strVersion, 64);
BYTE bytColorSt = RED;
string strRemark;
FILE *fp = NULL;
char version[130] = { 0 };
BOOL bFoundVersion = FALSE;
fp = _popen("java -version 2>&1", "r");
while (fp && fgets(version, sizeof version, fp))
{
string strTmp = version;
if (strTmp.find("version") != string::npos)
{
bFoundVersion = TRUE;
break;
}
}
if(fp) _pclose(fp);
....
PoolMon 跟踪
内存:33401164K 可用:30057324K PageFlts:92362 InRam Krnl:20212K P:776328K 提交:3228052K 限制:37595468K 峰值:4747992K 池 N:182820K P:782568K 系统池信息 标记类型 Allocs 释放每个 Alloc 的差异字节
托克传呼 10546816 (390) 10319712 (382) 227104 324868080 (11392) 1430
CM31 分页 42886 ( 0) 20849 ( 0) 22037 101154816 ( 0) 4590
座位 44678436 (1662) 43769798 (1630) 908638 87253680 (3072) 96
QINi 已分页 234 ( 0) 1 ( 0) 233 60293216 ( 0) 258769
MmSt 分页 2683066 (79) 2670922 (83) 12144 27223856 (3312) 2241
【问题讨论】:
-
通常涉及资源获取的内存泄漏(例如对
_popen的调用)来自于未能释放该资源(即对_pclose的相应调用)。您是否尝试将代码简化为只调用 _popen/_pclose 的小程序? -
我发现的另一件事是,一些错误仅在您大规模运行应用程序时才会出现。当它在您的实验室中“运行干净”时,输入数据样本与客户的完整数据相比有多大?
-
_popen() 生成命令提示符以在 30 秒的计时器上获取已安装的 Java 版本信息。同样从日志中观察到 FILE 指针对关闭是有效的
-
不知道Java子进程在客户机器上是不是从来不退出?这可能会导致您的 fgets() 调用永远不会返回,因此 _pclose() 永远不会被调用。也许客户的 Java.exe 以某种方式损坏,或者另一个名为 Java.exe 的程序位于命令路径中并被执行?
-
顺便说一句:如果“版本”的输出在中间被 130 字符缓冲区剪切,您将找不到它。
标签: c++ windows memory-leaks pool