//习惯性写法,设置结构体后,立即声明结构体的尺寸,为后续malloc提供方便
const ULONG SCListenAcceptTaskParamSize = sizeof(SCListenAcceptTaskParam);
//这里接收到连接请求,申请参数区域,将关键信息带入参数区域,帮助后续线程工作.
bool CListen::ListenTaskCallback(void* pCallParam,int& nStatus)
{
//正常的函数逻辑… …
//假定s是accept到的socket,需要传入后续线程工作
//在此准备一块参数区域,从远堆上申请
SCListenAcceptTaskParam* pParam = (SCListenAcceptTaskParam*) malloc(SCListenAcceptTaskParamSize);
//给参数区域赋值
pParam->m_nSocket = s;
//此处启动线程,将pParam传递给线程… …
//正常的函数逻辑… …
}
//这是线程函数,负责处理上文accept到的socket
bool CListen::ListenAcceptTask(void* pCallParam,int& nStatus)
{
//第一句话就是强制指针类型转换,获得外界传入的参数区域
SCListenAcceptTaskParam* pParam= (SCListenAcceptTaskParam*)pCallParam;
//正常的函数逻辑… …
//退出前,必须要做的工作,确保资源不被泄露
close(pParam->m_nSocket); //关闭socket
free(pCallParam); // free传入的参数区域
//… …
}
四、内存bug
无规则的滥用内存和指针会导致大量的bug,程序员应该对内存的使用保持高度的敏感性和警惕性,谨慎地使用内存资源.
使用内存时最容易出现的bug是:
(1)坏指针值错误:在指针赋值之前就用它来引用内存,或者向库函数传送一个坏指针,第三种可能导致坏指针的原因是对指针进行释放之后再访问它的内容.可以修改free语句,在指针释放之后再将它置为空值.
free(p); p = NULL;
这样,如果在指针释放之后继续使用该指针,至少程序能在终止之前进行信息转储.
(2)改写(overwrite)错误:越过数组边界写入数据,在动态分配的内存两端之外写入数据,或改写一些堆管理数据结构(在动态分配内存之前的区域写入数据就很容易发生这种情况)
p=malloc(256);p[-1]=0;p[256]=0;
(3)指针释放引起的错误:释放同一个内存块两次,或释放一块未曾使用malloc分配的内存,或释放仍在使用中的内存,或释放一个无效的指针.一个极为常见的与释放内存有关的错误就是在 for(p=start;p=p->next) 这样的循环中迭代一个链表,并在循环体内使用 free(p) 语句.这样,在下一次循环迭代时,程序就会对已经释放的指针进行解除引用操作,从而导致不可预料的结果.
我们可以这样迭代:
struct node *p, *tart, *temp;
for(p = start; p ; p = temp)
{
temp = p->next;
free(p);
}
//…
}