如何在对象的整个生命周期中保持指针字段不变(C++ 中管道的句柄)

问题描述 投票:0回答:1

我正在尝试创建一个处理程序类来处理 C++ 中的管道。首先我可能会说我已经习惯了 C#,但对 C++ 和指针的概念还很陌生。

类中唯一的字段是一个变量,类型为 HANDLE (void *),

pipeHandle
,它存储
CreateFile()
返回的值。

我有一个方法,

ConnectPipe()
,它使用
CreateFile()
来获取管道的句柄,以及一些错误检查。它将句柄存储在
pipeHandle
中,然后完成执行。这似乎是有问题的,因为经过研究和调试,我发现
pipeHandle
的值在
ConnectPipe()
执行完成后发生了变化。我认为这是由于指针引用了
ConnectPipe()
中实例化的内容,然后在
ConnectPipe()
完成后被删除。

代码:

PipeManager.h:

#ifndef PIPE_MANAGER_H
#define PIPE_MANAGER_H

#include <Windows.h>
#include <string>

class PipeManager
{
private:
    HANDLE pipeHandle;
    void PipeConnect(LPCWSTR pipeFullName);
    void PipeReceive(BYTE* outBuffer);

public:
    PipeManager(std::string pipeName);
    void Testing();
};

#endif

管道管理器.cpp:

#include "PipeManager.h"
#include <iostream>

void PipeManager::PipeConnect(LPCWSTR pipeFullName)
{
    const int ATTEMPT_LIMIT = 10;
    int attempts = 0;

    do {
        if (attempts > ATTEMPT_LIMIT) {
            break;
        }
        pipeHandle = CreateFile(pipeFullName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
        if (pipeHandle == INVALID_HANDLE_VALUE) {
            std::cerr << "Failed to connect to the named pipe, error code " << GetLastError() << ". Trying again." << std::endl;
            attempts++;
        }
    } while (pipeHandle == INVALID_HANDLE_VALUE);
}

void PipeManager::PipeReceive(BYTE* outBuffer)
{
    DWORD read = 0; // Number of bytes read in each ReadFile() call
    int index = 0;
    do {
        if (!ReadFile(pipeHandle, outBuffer + index, 1, &read, NULL)) {
            std::cerr << "Failed to read from the named pipe, error code " << GetLastError() << std::endl;
            break;
        }
    } while (outBuffer[index - 1] != 0); // Stop if the most recent byte was null-termination.
}

// Constructor for a named pipe, yet to be connected to
PipeManager::PipeManager(std::string pipeName) {
    std::string fullName = "\\\\.\\pipe\\" + pipeName;
    PipeConnect(std::wstring(fullName.begin(), fullName.end()).c_str());
}

void PipeManager::Testing()
{
    BYTE buffer[1024];
    PipeReceive(buffer);
}

CPPClient.cpp(应用程序入口点):

int main()
{
    //return HandlePipe("TestingPipe", false);
    PipeManager pipeManager = new PipeManager(std::string("TestingPipe"));
    pipeManager.Testing();
}

我有一个正在运行的管道服务器(用 C# 编写),它创建“TestingPipe”,我知道它可以工作并且已经过测试。我还设法让管道客户端(用 C++ 编写)工作,但不在类内 - 只是一堆函数调用和

main()
方法中的内容。 当我运行上面的程序时,C# 服务器最初接受连接,但当客户端尝试读取“管道已损坏”时失败,而 C++ 客户端在尝试从管道读取时失败,并显示代码 6 无效句柄。

如何在对象的整个生命周期中保持

pipeHandle
不变,或者至少在
ConnectPipe
完成初始化后停止更改?

除非这是不可能的,在这种情况下,我每次想读取或写入管道时都必须重新连接到管道。

编辑: 删除不相关的代码

c++ winapi pipe
1个回答
0
投票

非常感谢 Igor Tandetnik - 在我的

main()
函数中,我使用了
new
关键字,它创建一个对象并将其复制到一个新对象中。正是这个导致了
pipeHandle
的改变,而不是我最初认为的引用问题。

© www.soinside.com 2019 - 2024. All rights reserved.