我正在制作一个客户端服务器应用程序,服务器具有 GUI。我正在使用 Qt。 对于通信,我使用管道。
我已将服务器应用程序分为后端和 GUI。后端有一个 PipeServer 类,在 GUI 中,我重写了 onReceiveMessage 等函数。
一切正常,直到我决定添加一个 std::queue 作为基类成员。
在应用程序启动时,我遇到异常,经检查似乎我的队列不是从 0 个元素开始的。事实上,队列似乎根本没有初始化。有两种可能性:可能是因为我的 GUI 类继承了 2 个类,不知何故第二个基类,即我的 PipeServer 没有正确初始化其成员,或者可能是因为 pipeServerGUI 对象被移动到另一个线程QT.
关于如何解决这个问题有什么想法吗?
相关代码:
class HookServer
{
PIPEINST Pipe[INSTANCES];
HANDLE hEvents[INSTANCES];
VOID DisconnectAndReconnect(DWORD);
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);
VOID GetAnswerToRequest(LPPIPEINST);
public:
std::queue<std::string> messages;
int init(std::string pipename);
int run();
virtual void onNewConnection() {};
virtual void onReceiveMessage(std::string message) {};
};
class HookServerGUI : public QObject, public HookServer
{
Q_OBJECT
void onReceiveMessage(std::string message);
void onNewConnection();
public slots:
void doWork() {
init("\\\\.\\pipe\\hookpipe");
run();
}
signals:
void signalGUI(QString message);
};
//GUIServerCreation
QThread *thread = new QThread;
HookServerGUI* worker = new HookServerGUI;
QObject::connect(worker,SIGNAL(signalGUI(const QString&)),this,SLOT(processMessage(const QString&)));
worker->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(worker, "doWork", Qt::QueuedConnection);
编辑:
异常是访问冲突异常。它发生在这部分代码中:
VOID HookServer::GetAnswerToRequest(LPPIPEINST pipe)
{
onReceiveMessage(pipe->chRequest);
if(!messages.empty())
{
std::string s = messages.front();
messages.pop();
strcpy(pipe->chReply,s.c_str());
pipe->cbToWrite = strlen(s.c_str()+1);
}
}
由于 messages.empty() 返回了一些巨大的数字,它尝试读取第一个对象但不知何故失败了。
也没有 PipeServerGUI 构造函数。
编辑2:
我通过在 new HookServerGUI();
问题是该函数仍然不起作用,并抛出访问冲突异常。它发生在 front() 行。在调试器中检查时,该函数确实有 1 个元素,所以它不是因为它是空的。有什么想法吗?
编辑3:
第二次运行时,不幸的是 queue.size() 仍然不正确。对我来说,这就像一场数据竞赛。
最佳答案
问题出在您没有显示的代码中,它看起来像是内存错误的典型案例。某处的某些代码正在写入它不拥有的内存。可能您在使用 winapi 的方式上存在错误。您需要创建一个最小的、独立的测试用例。
我认为您不使用 QLocalSocket
可能是搬起石头砸自己的脚:在 Windows 上,它是一个命名管道 - 正是您想要的。
此外,这是C++代码。根本没有理由将 PIPEINST 或 HANDLE 放入原始 C 数组中。使用 QVector
或 std::vector
。可能代码的其余部分充满了这样的 C 主义,并且某处出了问题。
我不会忽视缓冲区溢出,因为显然您忽略了 PIPEINST 中缓冲区的大小 - strcpy
可能会溢出缓冲区。我也不确定 PIPEINST from the example code使用与 std::string::c_str()
返回的字符类型相同的字符类型。
即使您想在没有 QLocalSocket
的情况下使用显式管道实现您的代码,您仍然应该使用 C++、QString
等,并了解您的数据发生了什么。
关于c++ - 公共(public)成员未初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21148032/