object 超出 switch case 范围时的访问冲突

Access violation when the object goes out of scope in switch case

好的,那么。我开始学习 C++,我的任务是用 Win32 API 创建一个进程管理器。它看起来像这样:

我有一个 TBuffer class:(缓冲区将保留有关进程的信息)

#pragma once

#include <wtypes.h>

#define BUFFER_SIZE 10
#define WM_UPDATELIST WM_USER

enum TProcessState { psEmpty, psNew, psRunning, psTerminated, psError };

struct TProcessInfo 
{
    TProcessState State;
    char Name[100];
    HANDLE Handle;
    int PID;
    int UserTime, KenelTime;
};

class TBuffer
{
private:
    HWND Wnd;
    CRITICAL_SECTION cs;
    TProcessInfo Buf[BUFFER_SIZE];
public:
    TBuffer(HWND AWnd);
    ~TBuffer();
    int Count();
    int AddProcess(char *AName);
    void Get(int Id, TProcessInfo &Pi);
    void Set(int Id, const TProcessInfo Pi);
    const char* ProcessStateToString(TProcessState state);
};

class构造函数实现如下:

TBuffer::TBuffer(HWND AWnd)
{
    Wnd = AWnd;
    InitializeCriticalSection(&cs);
    for (int i = 0; i < BUFFER_SIZE; i++)
    {
        Buf[i].State = psEmpty;
        Buf[i].Handle = 0;
        Buf[i].Name[0] = 0;
        Buf[i].PID = 0;
        Buf[i].UserTime = 0;
        Buf[i].Handle = 0;
    }
}

以及析构函数:

TBuffer::~TBuffer()
{
    DeleteCriticalSection(&cs);
}

使用临界区的方法:

void TBuffer::Set(int Id, const TProcessInfo Pi)
{
    EnterCriticalSection(&cs);
    ...
    LeaveCriticalSection(&cs);
}

在主 .cpp 文件中,我有一个全局变量:

TBuffer *Buffer;

并且在处理消息的MainWndProc函数中,在WM_INITDIALOG的情况下,我被要求创建一个TBufferclassobject来初始化关键部分等等:

case WM_INITDIALOG:
{
    TBuffer Buf(hWnd);
    Buffer = &Buf;
    ...
    return TRUE;
}

我的问题是,正如我所读,return TRUE 之后的 class object 超出范围并调用其析构函数。这就是为什么关键部分被删除,然后其他 Set()Get() 等 class 方法无法进入关键部分的原因。所以我正在寻找一种将 object 留在范围内的方法。我认为 WM_INITDIALOG 和 object 创作有问题。

顺便说一句,在处理 WM_DESTROY 消息时,我释放了为全局变量分配的内存:

case WM_DESTROY:
    delete[] Buffer;
    PostQuitMessage(0);
    return TRUE;

你的理解是正确的,

case WM_INITDIALOG:
{
    TBuffer Buf(hWnd);
    Buffer = &Buf;
    ...
    return TRUE; // <-- Buf is destructed here, Buffer is now a dangling pointer
}

要分配比其封闭范围寿命更长的东西,请使用 new:

在堆上分配它
case WM_INITDIALOG:
{
    Buffer = new TBuffer(hWnd);
    ...
    return TRUE;
}

记得以后delete