sunmingming 发表于 2006-5-30 01:06:02

色兄,问您一个QT编程问题

最近决定为华为客户端写个界面,写得差不多了。但有个问题:

我从QObject和QThread派生出来一个类处理网络操作。

当连接时new一个对象出来,在断开连接时delete掉他。

但是现在每当delete时程序就会崩溃。

看了些文档,也用了deleteLater()。但当其真正消除对象的时候,仍然会崩溃。

该类声明如下:

        class HuaweiNetwork:public QObject, public QThread
        {
       
        Q_OBJECT
                u_charm_DestMac[6];        //目标MAC
                pcap_t *m_fp;                        //网卡设备
                USERDATA m_Data;//用户数据
                bool isonline;
       
                signals:
                        void Message(const char *);       
                        void Connected();
                        void ConnectionInterrupted();
                       
                protected:
                        bool SendVersion(const u_char Id);
                        bool SendUsername(const u_char Id);
                        bool SendPassword(const u_char Id, const u_char *Chap);
                        bool SendKeeponline(const u_char Id);
                       
                        bool OpenAdapter();
                        void CloseAdapter();
                       
                        void SetMd5Buf(PPASSWORDFRM pBuf, const u_char ID, const u_char *chap);
                        void InitBuf(u_char *buf);
               
                        bool SendLogin();
                        bool SendLogout();

                        virtual void run();
                       
        public:
                HuaweiNetwork(const QString & username, const QString & passwd, const QString & interfacenum, int * ip, int *mac);
                void Connect();
                void DisConnect();

        };


不知您是否也在写这个界面。如果您写了,我就不写了。不过还请您帮忙解决上面的问题。

多谢!

yunfan 发表于 2006-5-30 01:34:55

色兄还没来, 我先随便说几句:lol:

在qt 3中, 跨线程, 不能互相收发signal。 用 QApplication::postEvent
sub classQCustomEvent 类,自己定义一个event。


另外, 确保线程已经停止运行后, 删除这个对象,如果导致崩溃, 基本都是有所谓的“野指针”引起的。 还有, 在Qt 编程中, 但凡继承 QObject 来的类, 在程序退出时, qt 会自动删除这个对象, 不会造成内存泄漏。 所以, 既然你sub class 了 Qbject, 你也可以让 qt 自己来删。


发言完毕。 :-D

sejishikong 发表于 2006-5-30 08:48:30

呵呵,我的QT还只是初学,yunfan要比我强多了,所以我不发言了(其实是不会) :mrgreen:

sunmingming 发表于 2006-5-30 10:10:05

色兄还没来, 我先随便说几句:lol:

在qt 3中, 跨线程, 不能互相收发signal。 用 QApplication::postEvent
sub classQCustomEvent 类,自己定义一个event。


另外, 确保线程已经停止运行后, 删除这个对象,如果导致崩溃, 基本都是有所谓的“野指针”引起的。 还有, 在Qt 编程中, 但凡继承 QObject 来的类, 在程序退出时, qt 会自动删除这个对象, 不会造成内存泄漏。 所以, 既然你sub class 了 Qbject, 你也可以让 qt 自己来删。


发言完毕。 :-D

谢谢yunfan!

不过我的代码从线程中向界面发signal,界面是可以收到的。我查看的是Qt assistant:

The Signals and Slots mechanism can be used in separate threads, as long as the rules for QObject based classes are followed. The Signals and Slots mechanism is synchronous: when a signal is emitted, all slots are called immediately. The slots are executed in the thread context that emitted the signal.
Warning: Slots that generate window system events or use window system functions must not be connected to a signal that is emitted from a thread that is not the GUI thread. See the Qt Library Mutex section above for more details.


我的这个对象并构造时并无指定parent,此时也会被QT自动删除么?

另外,我的代码要求在断开连接的时候就释放对象,以便再次连接的时候重新new一个出来。所以让QT自动删除似乎不可行。

我没有重新实现析构函数。但是delete的时候就会出错。此时确定线程已经终止,网卡已关闭。

请yunfan帮忙解决一下吧。我对QT的一些基本机制还不太熟。

sunmingming 发表于 2006-5-30 10:12:02

呵呵,我的QT还只是初学,yunfan要比我强多了,所以我不发言了(其实是不会) :mrgreen:

色兄谦虚了。

sopcast 的界面就是您写的吧?

yunfan 发表于 2006-5-30 11:57:27

:mrgreen:

体会一下这句:

Warning: Slots that generate window system events or use window system functions must not be connected to a signal that is emitted from a thread that is not the GUI thread.


你这个 thread 不是 qwidget 的继承类, 是个 非 GUI thread。 如果你要在gui 线程里修改一些有关界面的东西, 会有问题。Qt 程序中, 有关gui更新部分是独立的线程,其实就是你程序main进来以后的那个线程, QApplication 会开一个线程用来处理event, 它会通知gui线程(主线程来更新显示等等)。 我上面说的不合适, 先道歉。 因为跨线程, 我都不用signal这种机制(Qt 4 是后话了), 所以我说的有点经验主意了。 不好意思。

稀里糊涂的说了一堆, 就一个意思, qt 3 里不推荐跨线程的connect 信号和槽。 因为一点牵扯到界面更改, 就无效了。(我没记错的话, 是更新界面部分会失效)。


顺便怕一下色兄MP, 色兄谦虚了:mrgreen:

yunfan 发表于 2006-5-30 12:08:38

我的这个对象并构造时并无指定parent,此时也会被QT自动删除么?

你可以给它一个parent:-D , 没有parent的, qt 删不了。
不过你上面说的 delete 时 crash, 你还是再检查一下 你的实现文件, 应该有点问题。尤其是有关那几个指针变量, 还有析构函数的处理什么。

sunmingming 发表于 2006-5-30 17:42:15

今天查了一下午,终于查出来了……………………

原来是头文件顺序问题。bug是没了,但仍然有问题:

global.h中声明:


//防止为了字节对齐而在结构体中插入0
#pragma pack(push) // 将当前pack设置压栈保存
#pragma pack(1)// 必须在结构体定义之前使用
//一些结构声明
#pragma pack(pop) // 恢复先前的pack设置




包含时若将其放在最前,:

#include "global.h"
#include "pcap.h"
#include <qobject.h>
#include <qstring.h>
#include <qthread.h>

namespace NetworkOperation{
class HuaweiNetwork:public QObject, public QThread
{
        Q_OBJECT
        …………
};
}


则会崩溃,但若将global.h放到最后,则不会崩溃。
#pragma pack(pop)之后的 pack设置应该已经恢复默认了吧?

为什么会对下面的代码产生影响呢?

sunmingming 发表于 2006-5-30 17:47:58

谢谢yunfan。呵呵,您真是太客气了。以后要多多向您学习。

ricetons 发表于 2006-5-30 21:23:51

好像很复杂的样子。要用到多重继承。

还是Qt本身设计就是这样的。

heyuqi 发表于 2006-5-30 21:45:09

现在做界面我更倾向于使用 XML 之类的语言来描述,比较简单明了。

sunmingming 发表于 2006-5-30 23:22:50

好像很复杂的样子。要用到多重继承。

还是Qt本身设计就是这样的。

QT文档中有这样的代码例子。

如果要在线程中向外发消息,这个应当是比较方便的方法。

当然也可以用 friend class 加Thread成员的方式,但是毕竟不如这样方便。

sunmingming 发表于 2006-5-30 23:25:55

现在做界面我更倾向于使用 XML 之类的语言来描述,比较简单明了。

这是我第一次写正儿八经的界面程序。呵呵,以前都是控制台或者matlab。

目前觉得QT还不错。

heyuqi兄所说的方式我还不太了解。以后还要向诸位前辈多多学习。
页: [1]
查看完整版本: 色兄,问您一个QT编程问题