我有2个程序,一个使用Windows API获取所有进程信息,并将它们存储在这样的结构 vector 中:

struct Info{
  int pid,ppid;
  char exeName[256];
}
当我用数据填充结构时,我将back_pushing结构保留在 vector 中。
现在,我尝试使用memcpy()来存储映射文件中的数据,但是在第二个程序中无法正确读取它。您能帮我弄清楚如何正确读取数据吗?
代码程序1:
    #define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <stdio.h>
#include <Tlhelp32.h>
#include <vector>

struct InfoProces {
    DWORD pid;
    DWORD ppid;
    char  exeName[256];
};

int main(){
    HANDLE hProcesses;
    PROCESSENTRY32 pe32;

    hProcesses = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if (hProcesses == INVALID_HANDLE_VALUE)
    {
        printf("CreateToolhelp32Snapshot failed. err = %d", GetLastError());
        return -1;
    }

    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hProcesses, &pe32)) {
        printf("Process32First failed. err = %d", GetLastError());
        CloseHandle(hProcesses);
        return -1;
    }


    HANDLE hdata = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024 * 1024, "data");
    if (hdata == NULL) {
        printf("Can't create a file mapping. err = %d", GetLastError());
        return -1;
    }

    unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
    if (pdata == NULL) {
        printf("cant get pointer to mapping file. err = %d", GetLastError());
        return -1;
    }



    do {
        InfoProces pi;
        pi.pid = pe32.th32ProcessID;
        pi.ppid = pe32.th32ParentProcessID;
        strcpy(pi.exeName, pe32.szExeFile);


    } while (Process32Next(hProcesses, &pe32));


    getchar();
    CloseHandle(hProcesses);
    return 0;
代码程序2:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <vector>
#include <stdio.h>

struct InfoProces {
    DWORD pid;
    DWORD ppid;
    char  exeName[256];
};

int main()
{
    HANDLE hdata = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, "data");

    unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
    if (pdata == NULL) {
        printf("cant get pointer to mapped file. err = %d", GetLastError());
        return -1;
    }
    std::vector<InfoProces>processes;

    memcpy(&processes,pdata,sizeof(data));

    for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
        printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);

    return 0;
}

最佳答案

正如评论所指出的那样,您已经获得了映射 View 的起始地址(pdata),您只能使用pdata进行内存共享,而不能使用该进程的任何堆栈地址。
尝试将InfoProces的内存复制到程序1中的pdata:

memcpy(pdata, &pi, sizeof(InfoProces));
此外,在程序2中,您没有设置 vector 的大小,应将&processes替换为processes.data()。您还需要知道在程序1中添加的数组的大小:
std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);
以下代码对我有用。
程序1 :(记录InfoProces的计数并将其保存到pdata开头的DWORD中)
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_WRITE, 0, 0, 0);
if (pdata == NULL) {
    printf("cant get pointer to mapping file. err = %d", GetLastError());
    return -1;
}

unsigned char* begin = pdata;

//offset a size of DWORD;
DWORD count = 0;
pdata += sizeof(DWORD);

do {
    InfoProces pi;
    pi.pid = pe32.th32ProcessID;
    pi.ppid = pe32.th32ParentProcessID;
    strcpy(pi.exeName, pe32.szExeFile);
    memcpy(pdata, &pi, sizeof(InfoProces));
    pdata += sizeof(InfoProces);
    count++;
} while (Process32Next(hProcesses, &pe32));

memcpy(begin, &count, sizeof(DWORD));

getchar();
UnmapViewOfFile(begin);
CloseHandle(hdata);
CloseHandle(hProcesses);
...
程式2:
...
unsigned char* pdata = (unsigned char*)MapViewOfFile(hdata, FILE_MAP_READ, 0, 0, 0);
if (pdata == NULL) {
    printf("cant get pointer to mapped file. err = %d", GetLastError());
    return -1;
}
unsigned char* begin = pdata;
DWORD count = 0;
memcpy(&count, pdata, sizeof(DWORD));
pdata += sizeof(DWORD);

std::vector<InfoProces> processes;
processes.resize(count);
memcpy(processes.data(), pdata, sizeof(InfoProces)*count);

for (std::vector<InfoProces>::iterator i = processes.begin(); i < processes.end(); i++)
    printf("Process[%d](parinte[%d]): %s\n", i->pid, i->ppid, i->exeName);
UnmapViewOfFile(begin);
CloseHandle(hdata);
...
最后,不要忘记关闭句柄和取消映射地址。

10-07 19:32
查看更多