能力值:
( LV2,RANK:10 )
|
-
-
2 楼
awesomeness!!!!
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
我的是win7系统,64版本的。是的都试一试,任务管理器的性能里句柄数不断增加,内存使用有增无减。你的机子要是24小时开机,此程序要是24小时运行的话,电脑就会变慢,最后跑不动了。
|
能力值:
( LV3,RANK:30 )
|
-
-
4 楼
虽然看不懂楼主在表达什么,为了谁而表达,但是看起来好厉害的样子!!
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
你在说什么 - -||| 我说的是句柄泄漏啊,谁试谁泄漏
|
能力值:
( LV3,RANK:30 )
|
-
-
6 楼
bdwdd(1467956605) 2013-7-25 15:05:57
查看前后消息用死循环24小时测试自己的函数,过了差不多一天后发现内存不足?我new的都有delete啊?怎么回事?
2013-07-30, 10:11:50 【讨论】真相是CreateProcessWithLogonW句柄泄漏!!!
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
你居然贴出了q群里的对话
|
能力值:
( LV5,RANK:70 )
|
-
-
8 楼
Mark!!
|
能力值:
( LV2,RANK:10 )
|
-
-
9 楼
CreateProcessWithLogonW
有create 就没有相应的destroy吗
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
waitForSigleObject就是等它结束了,没什么destroy。微软一天不修补这个我一天不用这个函数,创建一个进程居然隐藏了那么多句柄要人释放
|
能力值:
( LV12,RANK:200 )
|
-
-
11 楼
msdn中有例子,你看看你用的和人家用的有啥不同?
有句柄泄漏,M$的人肯定有测试出来.
vs2008 msdn : ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dllproc/base/createprocesswithlogonw.htm
#define UNICODE
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <userenv.h>
void DisplayError(LPWSTR pszAPI)
{
LPVOID lpvMessageBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&lpvMessageBuffer, 0, NULL);
//
//... now display this string
//
wprintf(L"ERROR: API = %s.\n", pszAPI);
wprintf(L" error code = %d.\n", GetLastError());
wprintf(L" message = %s.\n", (LPWSTR)lpvMessageBuffer);
//
// Free the buffer allocated by the system
//
LocalFree(lpvMessageBuffer);
ExitProcess(GetLastError());
}
void wmain(int argc, WCHAR *argv[])
{
DWORD dwSize;
HANDLE hToken;
LPVOID lpvEnv;
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
WCHAR szUserProfile[256] = L"";
si.cb = sizeof(STARTUPINFO);
if (argc != 4)
{
wprintf(L"Usage: %s [user@domain] [password] [cmd]", argv[0]);
wprintf(L"\n\n");
return;
}
//
// TO DO: change NULL to '.' to use local account database
//
if (!LogonUser(argv[1], NULL, argv[2], LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, &hToken))
DisplayError(L"LogonUser");
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
DisplayError(L"CreateEnvironmentBlock");
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
DisplayError(L"GetUserProfileDirectory");
//
// TO DO: change NULL to '.' to use local account database
//
if (!CreateProcessWithLogonW(argv[1], NULL, argv[2],
LOGON_WITH_PROFILE, NULL, argv[3],
CREATE_UNICODE_ENVIRONMENT, lpvEnv, szUserProfile,
&si, &pi))
DisplayError(L"CreateProcessWithLogonW");
if (!DestroyEnvironmentBlock(lpvEnv))
DisplayError(L"DestroyEnvironmentBlock");
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
是,经过ms测过的都没问题。windows不存在句柄泄漏。
我的是死循环,它才执行了一次能看出什么
|
能力值:
( LV12,RANK:200 )
|
-
-
13 楼
你咋看得句柄泄漏结果? 抓图上来.
|
能力值:
( LV12,RANK:200 )
|
-
-
14 楼
MS的用法是执行了一次,你在外面包了一层死循环,将你看句柄泄漏的界面截图上来。我给你改一个没有句柄泄漏的.
你看句柄泄漏用的啥工具? 截个图贴上来.
|
能力值:
( LV12,RANK:200 )
|
-
-
15 楼
你用任务管理器,怎么看到的是你的测试程序句柄数量不断增加的?
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
任务管理器有个性能选项卡,里面可以看到句柄数猛增!只要执行了这个循环就会。。所以这个函数句柄泄漏,至少说这个函数不可以用在服务器进程上,会卡慢服务器。。
|
能力值:
( LV12,RANK:200 )
|
-
-
17 楼
MS提供的Demo, 测试不可能是跑一遍就算了的. 白盒测试,黑盒测试.
长时间运行测试,人家都是搞过的.
你很喜欢用撞墙的表情啊~~
我知道您的测试(句柄泄漏)方法了, 我给您改一个句柄不泄漏的.
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
反正我死循环用CreateProcessAsUser来创建那个进程,然后关掉各种句柄系统没问题,内存使用也正常,就是换了这个CreateProcessWithLogonW函数就不行了,系统句柄数几百几百地增加,内存使用也一直增加,最后结果只有一个,系统跑不动了!
|
能力值:
( LV12,RANK:200 )
|
-
-
19 楼
CreateProcessWithLogonW API那失败, 别人那也遇到过.
说是域用户才可以成功.
我这没有域用户, 实验做不下去了.
我的环境Win7X64Sp1.
你用本地账户可以 ? CreateProcessWithLogonW 不失败?
你给的那段代码, 在vs2008下编译通不过, 是你做实验的Demo么?
我将MS的例子编译过了, 但是到 CreateProcessWithLogonW 处会失败
ERROR: API = CreateProcessWithLogonW.
error code = 0x422.
message = 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。
你能将你做实验的那个Demo工程, 在本地实验完了,传到主贴么?
// srcOK.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <userenv.h>
#include <locale.h>
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Userenv.lib")
#define G_LOGIN_NAME L"administrator"
#define G_LOGIN_PWD L"1"
#define G_PROG_NAME L"C:\\windows\\system32\\notepad.exe"
void DisplayError(LPWSTR pszAPI)
{
LPVOID lpvMessageBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&lpvMessageBuffer, 0, NULL);
//
//... now display this string
//
wprintf(L"ERROR: API = %s.\n", pszAPI);
wprintf(L" error code = 0x%X.\n", GetLastError());
wprintf(L" message = %s.\n", (LPWSTR)lpvMessageBuffer);
//
// Free the buffer allocated by the system
//
LocalFree(lpvMessageBuffer);
_tprintf(L"Error, press any key to quit");
getwchar();
ExitProcess(-1);
}
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bIsLocalUser = TRUE;
DWORD dwSize = 0;
HANDLE hToken = NULL;
LPVOID lpvEnv = NULL;
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
WCHAR szUserProfile[256] = {0};
setlocale(LC_CTYPE, ".936"); //< 控制台为中文输出
si.cb = sizeof(STARTUPINFO);
//
// TO DO: change NULL to '.' to use local account database
//
if (!LogonUser( G_LOGIN_NAME,
NULL,
G_LOGIN_PWD,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&hToken))
{
DisplayError(L"LogonUser");
}
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE))
DisplayError(L"CreateEnvironmentBlock");
dwSize = sizeof(szUserProfile)/sizeof(WCHAR);
if (!GetUserProfileDirectory(hToken, szUserProfile, &dwSize))
DisplayError(L"GetUserProfileDirectory");
//
// TO DO: change NULL to '.' to use local account database
//
/**
ERROR: API = CreateProcessWithLogonW.
error code = 0x422.
message = 无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。
*/
/// 必须要判断是否为本地用户, 否则会出现0x422的错误
bIsLocalUser = (NULL != wcschr(G_LOGIN_NAME, L'@')) ? FALSE : TRUE;
/// 参数2 用 L"." 和 NULL 都实验过了
/// 好像用域用户才行, 本地用户不行
/// 我这没域用户的环境...
if (!CreateProcessWithLogonW(
G_LOGIN_NAME,
NULL, // bIsLocalUser ? L"." : NULL,
G_LOGIN_PWD,
LOGON_WITH_PROFILE,
NULL,
G_PROG_NAME,
CREATE_UNICODE_ENVIRONMENT,
lpvEnv,
szUserProfile,
&si,
&pi))
{
DisplayError(L"CreateProcessWithLogonW");
}
_tprintf(L"OK \r\n");
if (!DestroyEnvironmentBlock(lpvEnv))
DisplayError(L"DestroyEnvironmentBlock");
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
getwchar();
return 0;
}
你能将你做实验的那个Demo工程, 在本地实验完了,传到主贴么?
|
能力值:
( LV12,RANK:200 )
|
-
-
20 楼
你的代码进 if(abc) 判断了么?? 你打句日志看下.
CreateProcessWithLogonW 用本地账户会执行失败的.
if(abc)
{
::WaitForSingleObject(pi.hProcess,INFINITE);
::CloseHandle((HANDLE)(pi.hProcess));
::CloseHandle(pi.hThread);
::CloseHandle(si.hStdError);//这三个handle也释放了,结果还是句柄泄漏
::CloseHandle(si.hStdInput);
::CloseHandle(si.hStdOutput);
}
按照你的首帖上整理出来的工程, 原来是编译不过的.
你拿这个工程, 将用户名和口令改了,看在你那能运行么?
主要是看 CreateProcessWithLogonW 那是否执行成功
都按照你原先的来,只是整理.
整理后的能编译通过的工程 srcBad.rar
看你的代码,也不是域用户啊.
难道和Windows版本有关系?
|
能力值:
( LV2,RANK:10 )
|
-
-
21 楼
判断了,单步都能跟进去
代码:
void CwhileCreatePDlg::OnBnClickedButton1()
{
while(true)
{
HANDLE hp=NULL;
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory( &si, sizeof(si) );
si.wShowWindow = SW_SHOW;
si.lpDesktop = NULL;
si.cb=sizeof(STARTUPINFO);
si.dwFlags=STARTF_USESHOWWINDOW;
ZeroMemory( &pi, sizeof(pi) );
char pcName[MAX_COMPUTERNAME_LENGTH + 1]={};
int nameSize=MAX_COMPUTERNAME_LENGTH + 1;
::GetComputerNameA((LPSTR)&pcName,(LPDWORD)&nameSize);
BOOL abc;
abc=CreateProcessWithLogonW((LPCWSTR)L"abc",(LPCWSTR)&pcName,(LPCWSTR)L"1",LOGON_WITH_PROFILE,NULL,(LPWSTR)L"C:\\Users\\Administrator\\Desktop\\selfDestroy.exe",CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi);
if(abc)
{
::WaitForSingleObject(pi.hProcess,INFINITE);
::CloseHandle((HANDLE)(pi.hProcess));
::CloseHandle(pi.hThread);
::CloseHandle(si.hStdError);
::CloseHandle(si.hStdInput);
::CloseHandle(si.hStdOutput);
}
}
}
|
能力值:
( LV12,RANK:200 )
|
-
-
22 楼
你在我贴的那个工程上, srcBad.rar 那个工程在20楼的尾部, 试试, 是否能成功。
如果不成功,将那个工程改成能运行的.
将该改完的工程再传上来.
我这现在因为那个函数执行失败,没发再实验了。
你那的Windows是什么? winXp? Win7X64?
|
能力值:
( LV2,RANK:10 )
|
-
-
23 楼
那是肯定会增加句柄的好不? 又不是函数本身的问题 而是因为你创建的进程需要创建句柄. 比如新进程窗口和进程,及线程 多开一个进程,句柄就多出一部分.
|
能力值:
( LV12,RANK:200 )
|
-
-
24 楼
他的用法是守护进程
开一份进程,如果进程被结束了,关掉改观的句柄, 再开新的一份进程.
句柄数量不该持续增长.
|
能力值:
( LV2,RANK:10 )
|
-
-
25 楼
Win7 64位系统,没有发现泄漏。CreateProcessWithLogonW函数执行完后,只多出来对应进程和线程的两个句柄,关闭这两个后,句柄数恢复原值。
只有第一次执行CreateProcessWithLogonW后,会多出一些与logon和WindowStation相关的一些句柄,但这些句柄基本稳定,第二次和以后的CreateProcessWithLogonW执行,句柄数就如上所说的了。
建议不要看整个系统的句柄数,而应该看这个指定进程的句柄数。同时,尽量关闭杀毒软件等会对系统hook的程序,再重新测试,可能是第三方软件泄漏了。
|
|
|