项目中碰到的错误剖析

30 篇文章 0 订阅
4 篇文章 0 订阅

项目介绍:服务器Linux,客户端Windows,实现类似于QQ的功能

注释:部分仍然是疑惑

 1. 定义了一个消息头,格式如下

//消息头
typedef struct MsgHead
{
    char cSenderName[16];
    char cRecverName[16];
    int iMsgType;
    int msglen;
    char * data() { return (char *)(this+1); }
}MsgHead, *pMsgHead;

接收到消息时,拷贝内存的时候忘了把data(),也就是头部后面的内容拷贝过去;

实践证明,在char * 和结构体之间转换是安全的!

2.在一个线程中,定义了一段内存用来接收消息,假设为recvBuf[1024],之后调用处理函数handleMsg(const char * data, int dataLen)对其进行处理。但是出现了内存释放错误,分析原因:recvBuf中使用了const进行限定,所以当新的消息到来时,handleMsg()函数无法释放该段内存,导致出错。

3.多个线程访问同一个数据结构,用互斥锁时,出现死锁;但不用互斥锁时,线程A删除了某个元素,而线程B正好要去访问这个元素,内存访问出错,导致主线程自动退出?一点错误提示都没有??疑惑

4.在编写客户端时,有时候会出现内存访问错误。然后把代码遛了一圈,发现没有野指针什么的呀...而且该问题忽有忽无,感觉像是多线程引起的问题。果不其然,客户端用一段缓存来存放收到的数据,一旦消息传过来的比较多,处理不及的话导致的。主要原因在于,用AfxMessageBox()函数来做调试用,但也导致信息处理的暂停。注释掉AfxMessageBox()之后,问题不在。

5.客户端是用MFC实现的(比较老的东西了,估计大家都不用了)。在发送方发送消息之后,接收方接收到的消息都有乱码。以为是中间传参数的时候,字符数组跟指针复制的时候有问题,然后用strcpy()代替memcpy(),这样就只拷贝‘\0’之前(包括'\0')的有效字符了。但两头来回查,始终存在乱码问题。

后来突然想起来,在MFC下的CString类型的GetLength()函数好像是只取不包括'\0'的有效字符的,这样传递过去的时候,就会因为找不到截至符而出现乱码!

CString.GetLength()+1之后成功解决该问题。

6.关于字符数组跟指针。字符数组我在使用之前一般都用内存设置函数memset()使里面的字符全为0,这样当内存拷贝时,确定无疑会有终结符,属于比较保险的操作;但是,字符类型的指针就不同了,它一般都在有效字符后加终结符'\0',之后可能是其他内容。所以,在使用这两者时,还是尽量用字符类型的函数,如strcmp(),strcpy()等。我个人原先比较青睐内存操作函数,可能会出现一些问题。

比如  char * pName="china",char cName[16]={0}, memcpy(cName, "china", 16);

当用memcmp()函数进行比较时,就会出现结果不为0的情况;而如果使用strcmp()函数进行比较,结果则为0;因为strcmp()函数进行有效字符比较的缘故。

写东西时,数组/指针经常换着用,所以有时候也会出现问题(待确认)。

7. 关于多线程的问题。

问题:在服务器端,每个与客户端的通信都有单独的线程,需要删除线程池中的数据;主线程在有链接到来时,需要增加线程池中的数据;轮询线程则继续要读,也需要删除线程池中的数据

这样就至少有三个线程会访问线程池,因此需要用pthread_mutex来锁定,但是单纯用互斥锁又会导致死锁,需要配合条件变量pthread_cond_t来实现线程的等待和唤醒,以实现线程间的同步。

8. 套接字传送String的问题

问题:

string相当于是一个char *,网络传输指针一般都会有问题(除非本机器的线程通信)。

在C#中没有指针的概念,以为可以用string传输,但在验证的时候仍然出错

typedef struct _Info
{
	string name;
	string cipher;
	string signature;
}Info;
解决办法:

把内容放在结构体中,而不要把string类型的对象放进结构体。全部用char[]数组进行存放

在C#中,声明数组时一般不指定数组的大小,而是用new关键字来分配,因此需要重写结构体的构造函数

代码如下:

        struct Info
        {
	        public char[] name;
            public char[] cipher;
            public char[] signature;
            public Info()
            {
                name = new char[16];
                cipher = new char[16];
                signature = new char[256];
            }

            public Info(string name, string cipher, string signature)
            {
                this.name = new char[16];
                this.name=name.ToCharArray(0, 16);
                this.cipher = new char[16];
                this.cipher=cipher.ToCharArray(0, 16);
                this.signature = new char[256];
                this.signature=signature.ToCharArray(0, 16);
            }
        }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值