我正在制作客户端服务器应用程序,服务器具有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构造函数。
EDIT2:
我通过在new HookServerGUI();
问题是该函数仍然无效,并引发访问冲突异常。它发生在front()行。在调试器中检查时,该函数确实有1个元素,因此它不是因为它是空的。有什么想法吗?
EDIT3:
第二次运行时,不幸的是queue.size()仍然不正确。看起来像是对我的数据竞争。
答案 0 :(得分:0)
问题出现在你没有展示的代码中,这是一个典型的内存错误案例,它看起来像。某些代码在某处写入它不拥有的内存。可能你在使用winapi的方式上有一个错误。您需要创建一个最小的,独立的测试用例。
我认为你可能会因为不使用QLocalSocket
而在脚下拍摄:在Windows上,它是一个命名管道 - 正是你想要的。
此外,这是C ++代码。完全没有理由将PIPEINST或HANDLE放入原始C数组中。使用QVector
或std::vector
。可能其余的代码充满了像这样的C-isms,而某些地方出了问题。
我不会忽略缓冲区溢出,因为显然你忽略了PIPEINST中缓冲区的大小 - strcpy
可以超出缓冲区。我也不确定PIPEINST from the example code使用的字符类型与std::string::c_str()
返回的字符类型相同。
即使你想使用没有QLocalSocket
的显式管道来实现你的代码,你仍然应该使用C ++,QString
等,并了解你的数据发生了什么。