Win32程序卡死在循环里


#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <string.h>
#include <psapi.h>

WINAPI int WinMain(HINSTANCE hInstance, HINSTANCE hPreInstacne, LPSTR lpCmdLine, int nCmdShow)
{
    HANDLE pHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 process32;
    process32.dwSize = sizeof(process32);
    BOOL bReturn = Process32First(pHandle,&process32); 
    wchar_t* dest;
    int srcSize = strlen(lpCmdLine);
    dest = (wchar_t*)malloc((srcSize+1)*2);
    memset(dest,0,(srcSize+1)*2);
    mbstowcs(dest,lpCmdLine,srcSize); 
    *(dest+srcSize) = L'\0'; //dest = L"Twinkstar.exe"
    while(bReturn)
    { 
        if(!wcscmp(dest,(wchar_t*)process32.szExeFile))
        {
            LPSTR path = (LPSTR)malloc(256);
            memset(path,0,256);
            HANDLE process = OpenProcess(PROCESS_ALL_ACCESS ,FALSE,process32.th32ProcessID);
            GetModuleFileNameExA(process,NULL,path,sizeof(path));
            printf("%s",path);
            free(path);
            path = NULL;
            break;
        }
        Process32Next(pHandle,&process32);
    }
    free(dest);
    dest = NULL;
}
    
  • 需求:编写一个程序,传入进程名字,输出进程所在路径

  • 问题:程序运行后卡死

img

  • 打开GDB调试:
  • 传入参数 Twinkstar.exe:

    img

  • 第17行下断点:

    img


    img

  • 第17行dest = L""

    img

  • 步进,第18行dest="Twinkstar.exe"
  • dest成功接收了lpCmdLine的值传递

    img

  • 继续运行,GDB直接卡死,推测问题就在循环里

    img

程序问题比较多,主要是字符串转换错误,字符串比较不一致就会陷入死循环,做了修改,参考一下:
运行参数指定为"winlogon.exe"试一下:

int WINAPI  WinMain(HINSTANCE hInstance, HINSTANCE hPreInstacne, LPSTR lpCmdLine, int nCmdShow)
{
    HANDLE pHandle = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    PROCESSENTRY32 process32;
    process32.dwSize = sizeof(process32);
    BOOL bReturn = Process32First(pHandle, &process32);
    char* dest;
    int srcSize = strlen(lpCmdLine);
    dest = (char*)malloc(srcSize + 1);
    memset(dest, 0, srcSize + 1);
    strcpy(dest, lpCmdLine);
    *(dest + srcSize) = L'\0'; //dest = L"Twinkstar.exe"
    while (bReturn)
    {
        if (!strcmp(dest, process32.szExeFile))
        {
            LPSTR path = (LPSTR)malloc(256);
            memset(path, 0, 256);
            HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process32.th32ProcessID);
            int nErr = GetLastError();
            GetModuleFileNameExA(process, NULL, path, 256);
            printf("%s", path);
            free(path);
            path = NULL;
            break;
        }
        Process32Next(pHandle, &process32);
    }
    free(dest);
    dest = NULL;
}

用管理员权限运行,在循环里输出下每次
process32.szExeFile
看看卡在哪里了

第27行sizeof(path)不对,path不是数组是字符串指针,大小为4,所以你获取的结果只有盘符如c:\加上结尾0刚好4位。

根据您提供的代码,循环似乎是遍历正在运行的进程列表,并尝试匹配目标进程的名称。然后,它打开匹配进程的句柄,并获取其模块文件的路径。

代码中的问题可能导致程序卡死的原因有几个可能性:

如果没有匹配到目标进程,循环将无限执行,因为没有设置终止条件。为了避免这种情况,请添加一个适当的终止条件。

如果找到目标进程并成功获取其模块文件的路径,但在打印路径之前发生了错误,例如调用了无效的句柄或路径字符串,可能会导致程序卡死。请确保在使用路径之前检查返回值和错误条件,以避免潜在的问题。

以下是修复上述问题的修改后的代码:

#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <string.h>
#include <psapi.h>

int main()
{
    HANDLE pHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 process32;
    process32.dwSize = sizeof(process32);
    BOOL bReturn = Process32First(pHandle, &process32);
    wchar_t* dest;
    int srcSize = strlen(lpCmdLine);
    dest = (wchar_t*)malloc((srcSize + 1) * 2);
    memset(dest, 0, (srcSize + 1) * 2);
    mbstowcs(dest, lpCmdLine, srcSize);
    *(dest + srcSize) = L'\0'; //dest = L"Twinkstar.exe"
    while (bReturn)
    {
        if (!wcscmp(dest, (wchar_t*)process32.szExeFile))
        {
            LPSTR path = (LPSTR)malloc(256);
            memset(path, 0, 256);
            HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process32.th32ProcessID);
            if (process != NULL)
            {
                DWORD pathLength = GetModuleFileNameExA(process, NULL, path, 256);
                if (pathLength > 0)
                {
                    printf("%s", path);
                }
                else
                {
                    printf("Failed to get module file name.\n");
                }
                CloseHandle(process);
            }
            else
            {
                printf("Failed to open process.\n");
            }
            free(path);
            path = NULL;
            break;
        }
        bReturn = Process32Next(pHandle, &process32);
    }
    free(dest);
    dest = NULL;

    CloseHandle(pHandle);
    return 0;
}


请注意,我还添加了对打开句柄和获取模块文件路径的错误检查,并进行了相应的处理。另外,为了使代码在命令行下运行,将WinMain函数更改为main函数。

这些修改应该有助于避免程序卡死,并提供更好的错误处理和调试信息。

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据代码和调试信息,循环中的代码看起来没有明显的问题,可能是由于另一个正在运行的进程导致程序卡死。您可以尝试在循环内加入 Sleep() 函数,减少 CPU 的占用,让其他进程有机会运行。

另外,您在使用 GetModuleFileNameExA() 函数时传递的是 sizeof(path),这个值是指针变量 path 的大小,而不是指向的缓冲区大小。因此,您需要将第三个参数改为缓冲区的大小,即 256

以下是修改后的代码:

#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <string.h>
#include <psapi.h>
 
WINAPI int WinMain(HINSTANCE hInstance, HINSTANCE hPreInstacne, LPSTR lpCmdLine, int nCmdShow)
{
    HANDLE pHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    PROCESSENTRY32 process32;
    process32.dwSize = sizeof(process32);
    BOOL bReturn = Process32First(pHandle,&process32); 
    wchar_t* dest;
    int srcSize = strlen(lpCmdLine);
    dest = (wchar_t*)malloc((srcSize+1)*2);
    memset(dest,0,(srcSize+1)*2);
    mbstowcs(dest,lpCmdLine,srcSize); 
    *(dest+srcSize) = L'\0'; //dest = L"Twinkstar.exe"
    while(bReturn)
    { 
        if(!wcscmp(dest,(wchar_t*)process32.szExeFile))
        {
            LPSTR path = (LPSTR)malloc(256);
            memset(path,0,256);
            HANDLE process = OpenProcess(PROCESS_ALL_ACCESS ,FALSE,process32.th32ProcessID);
            GetModuleFileNameExA(process,NULL,path,256); // 将第三个参数改为缓冲区的大小
            printf("%s",path);
            free(path);
            path = NULL;
            break;
        }
        Sleep(10); //加入 Sleep() 函数
        bReturn = Process32Next(pHandle,&process32);
    }
    free(dest);
    dest = NULL;
}

希望这可以帮助您解决问题。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

在分析您提供的代码时,我注意到可能会导致程序卡死的一些问题。下面是我找到的问题和建议的更改:

  1. 在使用 mbstowcs 函数之前,您使用 strlen 获取了 lpCmdLine 的长度。但是,lpCmdLine 是一个 LPSTR 类型的参数,表示一个指向以 null 结尾的字符串的指针,而不是一个以 null 结尾的字符串本身。因此,您应该使用 strlen(lpCmdLine) 替换为 strlen((const char*)lpCmdLine),以将 lpCmdLine 强制转换为 const char* 类型。

  2. 在分配内存给 dest 变量之前,您需要确定需要分配的内存大小,而不仅仅是 srcSize。因为 srcSize 表示源字符串的长度(不包括 null 终止符),而 dest 是一个宽字符字符串。宽字符字符串的长度应该是 srcSize * sizeof(wchar_t)。因此,您可以将以下行:

dest = (wchar_t*)malloc((srcSize+1)*2);

更改为:

dest = (wchar_t*)malloc((srcSize + 1) * sizeof(wchar_t));
  1. 在使用 GetModuleFileNameExA 函数时,您传递了 sizeof(path),但是 path 是一个指针,sizeof(path) 将返回指针的大小,而不是指针指向的缓冲区的大小。您可以更改为使用一个固定的缓冲区大小,例如 MAX_PATH,或者通过 strlen(path) + 1 来获取动态分配缓冲区的大小。

  2. 在调用 CreateToolhelp32Snapshot 函数后,您需要检查返回的 pHandle 是否有效,以确保快照成功创建。您可以添加以下代码来检查 pHandle

if (pHandle == INVALID_HANDLE_VALUE) {
    // 快照创建失败,进行适当的错误处理
    return -1;
}

这些是我在代码中注意到的主要问题。请尝试对代码进行相应的更改,看看是否解决了程序卡死的问题。
望采纳。