如何正确地重新分配free()< d>结构?

时间:2015-04-28 09:40:22

标签: c windows multithreading pointers malloc

我想创建一个监控某些进程的程序。为此,我创建了一个结构,其中包含要监视的进程,另一个结构,包含哪些进程仍在运行,以及一个执行该工作的线程。在线程中,(包含正在运行的进程的结构)ProcArrayDisplay将是空闲的(),以清空结构,然后是malloc()&d,并再次填充。我不确定,如果这是最好的方式。这是我的问题。如果有2个或更多进程正在运行,我总是得到Access vioalation

我认为这是因为,struct的Counter是一个全局变量,当Thread修改它时,出现了问题。我尝试使用Critical sectionsInterLockedIncrement/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, &params, 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;
}

1 个答案:

答案 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];