我想创建一个监控某些进程的程序。为此,我创建了一个结构,其中包含要监视的进程,另一个结构,包含哪些进程仍在运行,以及一个执行该工作的线程。在线程中,(包含正在运行的进程的结构)ProcArrayDisplay
将是空闲的(),以清空结构,然后是malloc()&d,并再次填充。我不确定,如果这是最好的方式。这是我的问题。如果有2个或更多进程正在运行,我总是得到Access vioalation
。
我认为这是因为,struct的Counter是一个全局变量,当Thread修改它时,出现了问题。我尝试使用Critical sections
和InterLockedIncrement/InterLockedDecrement
,但我仍然得到Access violation
。
那么我做错了什么,我该怎么做呢?
提前致谢!
我的代码:
#include <Windows.h>
#include <Conio.h>
#include <process.h>
#include <TlHelp32.h>
struct ProcToQuery
{
wchar_t * ProcessName;
wchar_t * DisplayName;
};
struct ProcToQuery **ProcArrayQuery = NULL;
int ProcArrayCountQuery = 0;
struct ProcToDisplay
{
wchar_t * ProcessName;
wchar_t * DisplayName;
};
struct ProcToDisplay **ProcArrayDisplay = NULL;
volatile long ProcArrayCountDisplay = 0;
typedef struct
{
BOOL bKill;
}PARAMS, *PPARAMS;
void AddItemsToQueryArray( wchar_t * ProcessName, wchar_t * DisplayName );
void AddItemsToDisplayArray( wchar_t * ProcessName, wchar_t * DisplayName );
void FreeStruct();
void FreeStructDisplay();
BOOL IsProcessRunning( wchar_t * ProcessName, wchar_t * DisplayName );
unsigned __stdcall Thread( void *ArgList );
int _tmain(int argc, _TCHAR* argv[])
{
AddItemsToQueryArray( L"notepad.exe", L"Notepad" );
AddItemsToQueryArray( L"calc.exe", L"Calculator" );
PARAMS params;
params.bKill = FALSE;
unsigned int ThreadId;
for ( int i = 0; i < ProcArrayCountQuery; i++ )
{
if ( !IsProcessRunning( ProcArrayQuery[ i ]->ProcessName, ProcArrayQuery[ i ]->DisplayName ) )
{
// IsProcessRunning failed
return 1;
}
}
if ( ProcArrayCountDisplay == 0 )
{
printf( "\nNone of the processes are running" );
FreeStruct();
return 0;
}
HANDLE hThread = ( HANDLE )_beginthreadex( NULL, 0, Thread, ¶ms, 0, &ThreadId );
// do some work
Sleep(20000);
params.bKill = TRUE;
DWORD dwExitCode;
DWORD dwRet = WaitForSingleObject( hThread, 2000 );
if ( dwRet == WAIT_OBJECT_0 )
{
// the thread has terminated
GetExitCodeThread( hThread, &dwExitCode );
printf( "\nThread finished ExitCode = %d", dwExitCode );
}
else if ( dwRet == WAIT_TIMEOUT )
{
// thread still active
GetExitCodeThread( hThread, &dwExitCode );
printf( "\nThread still active ExitCode = %d", dwExitCode );
}
else if ( dwRet == WAIT_FAILED )
{
printf( "\nWaitForSingleObject failed = %d", GetLastError() );
}
CloseHandle( hThread );
_getch();
return 0;
}
void AddItemsToQueryArray( wchar_t * ProcessName, wchar_t * DisplayName )
{
struct ProcToQuery **tmp = ( struct ProcToQuery ** )realloc( ProcArrayQuery, ( ProcArrayCountQuery + 1 ) * sizeof( struct ProcToQuery * ) );
if ( tmp == NULL )
{
return;
}
ProcArrayQuery = tmp;
ProcArrayQuery[ ProcArrayCountQuery ] = ( struct ProcToQuery * )malloc( sizeof **ProcArrayQuery );
if ( ProcArrayQuery[ ProcArrayCountQuery ] == NULL )
{
return;
}
ProcArrayQuery[ ProcArrayCountQuery ]->ProcessName = _wcsdup( ProcessName );
ProcArrayQuery[ ProcArrayCountQuery ]->DisplayName = _wcsdup( DisplayName );
ProcArrayCountQuery++;
}//AddItemsToQueryArray
void AddItemsToDisplayArray( wchar_t * ProcessName, wchar_t * DisplayName )
{
struct ProcToDisplay **tmp = ( struct ProcToDisplay ** )realloc( ProcArrayDisplay, ( ProcArrayCountDisplay + 1 ) * sizeof( struct ProcToDisplay * ) );
if ( tmp == NULL )
{
return;
}
ProcArrayDisplay = tmp;
ProcArrayDisplay[ ProcArrayCountDisplay ] = ( struct ProcToDisplay * )malloc( sizeof **ProcArrayDisplay );
if ( ProcArrayDisplay[ ProcArrayCountDisplay ] == NULL )
{
return;
}
ProcArrayDisplay[ ProcArrayCountDisplay ]->ProcessName = _wcsdup( ProcessName );
ProcArrayDisplay[ ProcArrayCountDisplay ]->DisplayName = _wcsdup( DisplayName );
ProcArrayCountDisplay++;
}//AddItemsToDisplayArray
void FreeStruct()
{
for ( int i = 0; i < ProcArrayCountQuery; i++ )
{
if ( ProcArrayQuery[ i ]->DisplayName ) free( ProcArrayQuery[ i ]->DisplayName );
if ( ProcArrayQuery[ i ]->ProcessName ) free( ProcArrayQuery[ i ]->ProcessName );
if ( ProcArrayQuery[ i ] ) free( ProcArrayQuery[ i ] );
}
free( ProcArrayQuery );
FreeStructDisplay();
free( ProcArrayDisplay );
}//FreeStruct
void FreeStructDisplay()
{
for ( int i = 0; i < ProcArrayCountDisplay; i++ )
{
if ( ProcArrayDisplay[ i ]->ProcessName ) free( ProcArrayDisplay[ i ]->ProcessName );
if ( ProcArrayDisplay[ i ]->DisplayName ) free( ProcArrayDisplay[ i ]->DisplayName );
if ( ProcArrayDisplay[ i ] ) free( ProcArrayDisplay[ i ] );
ProcArrayCountDisplay--;
}
}
BOOL IsProcessRunning( wchar_t * ProcessName, wchar_t * DisplayName )
{
PROCESSENTRY32 process;
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( snapshot == INVALID_HANDLE_VALUE )
{
return FALSE;
}
ZeroMemory( &process, sizeof( process ) );
process.dwSize = sizeof( process );
if ( Process32First( snapshot, &process ) )
{
do
{
if ( ( _wcsicmp( process.szExeFile, ProcessName ) == 0 ) )
{
printf("\n%ls is running", ProcessName );
AddItemsToDisplayArray( ProcessName, DisplayName );
}
} while ( Process32Next( snapshot, &process ) == TRUE );
}
else
{
// Process32First failed
CloseHandle( snapshot );
return FALSE;
}
CloseHandle( snapshot );
return TRUE;
}
unsigned __stdcall Thread( void *ArgList )
{
PPARAMS pparams;
pparams = ( PPARAMS )ArgList;
while ( !pparams->bKill )
{
// Request ownership of the critical section.
// EnterCriticalSection( &CriticalSection );
FreeStructDisplay();
printf("\n----------------------------------------------------");
for ( int i = 0; i < ProcArrayCountQuery; i++ )
{
if ( !IsProcessRunning( ProcArrayQuery[ i ]->ProcessName, ProcArrayQuery[ i ]->DisplayName ) )
{
// IsProcessRunning failed
return 1;
}
}
if ( ProcArrayCountDisplay == 0 )
{
// no package to display
break;
}
// Release ownership of the critical section.
// LeaveCriticalSection( &CriticalSection );
Sleep( 1000 );
}
_endthread();
return 0;
}
答案 0 :(得分:1)
如果结构可以被不同的线程访问并重复使用多次,我建议:
mutex
/ lock
unlock
:环绕操作来保护它
memset
清空您的结构,即将所有字段设置为0 根据我的理解,你想&#34;清空&#34;您的结构memset
似乎是一个很好的解决方案(尽管您可以在需要时覆盖字段):它将修复访问冲突问题,因为您的结构仍然存在(在使用之前不要忘记检查字段值虽然)
如评论中所述,free
不会&#34;空&#34;你的结构:它只是标记你通过malloc
保留的内存再次可用。内容将保持不变,直到其他内容写入其中。
<强> [编辑] 强>
我的不好,我错过了你使用wcsdup
分配一个新的字符串free
的事实。
如果您事先知道要操作的字符串的最大大小,则可以避免这种情况:
struct ProcToQuery
{
wchar_t ProcessName[MAX_STRING_SIZE];
wchar_t DisplayName[MAX_STRING_SIZE];
};
然后您可以使用wcscpy
代替wcsdup
,而不需要新的分配。
ProcArrayQuery
:
struct ProcToQuery * ProcArrayQuery[MAX_QUERY];