C++中类成员使用前需要初始化的重要性
今天写程序的时候,创建了一个结构体:
struct BufferObj {
char* buf;
int bufLen;
SOCKADDR_STORAGE addr;
int addrLen;
struct BufferObj* next;
};
该结构体有一个next指针,本意是这个指针初始的时候应该为NULL,如果有新的BufferObj添加,这个next指针就会指向这个新添加的BufferObj,其实就是一个链表。
程序中有一个生产者线程使用enqueueBufferObj方法向链表里面添加BufferObj:
void enqueueBufferObj(ConnectionObj* connObj, BufferObj* bufferObj) {
EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);
if (connObj->pendingSendHead == NULL) {
connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
} else {
connObj->pendingSendTail->next = bufferObj;
connObj->pendingSendTail = bufferObj;
}
LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
}
还有一个消费者线程从这个链表里面取BufferObj:
BufferObj* dequeueBufferObj(ConnectionObj* connObj) {
BufferObj* res = NULL;
EnterCriticalSection(&connObj->sendRecvQueueCriticalSection);
if (connObj->pendingSendTail != NULL) {
res = connObj->pendingSendHead;
connObj->pendingSendHead = connObj->pendingSendHead->next;
if (connObj->pendingSendTail == res) {
connObj->pendingSendTail = NULL;
}
}
LeaveCriticalSection(&connObj->sendRecvQueueCriticalSection);
return res;
}
其中,ConnectionObj结构体如下:
struct ConnectionObj {
SOCKET s;
HANDLE hRecvSemaphore;
struct BufferObj* pendingSendHead;
struct BufferObj* pendingSendTail;
CRITICAL_SECTION sendRecvQueueCriticalSection;
};
刚开始的时候,由于程序中没有显示的将BufferObj的next属性初始化NULL,导致程序运行到enqueueBufferObj方法时总是出现指针违法访问:
connObj->pendingSendTail->next = bufferObj;
上面就是出错的地方。程序中对于ConnectionObj中的pendingSendHead和pendingSendTail都已经显示初始化为NULL了。经过查找发现,是因为程序中没有显式对
BufferObj中next进行NULL初始化,从而当消费者线程从队列中BufferObj之后,会重新对队列头进行初始化,该代码在dequeueBufferObj中:
connObj->pendingSendHead = connObj->pendingSendHead->next;
此时,如果BufferObj中的next显示初始化为了NULL,那么connObj->pendingSendHead的值应该为NULL,但是程序中没有对next进行显式初始化,所以,此时,
connObj->pendingSendHead的值为一个随机值,这导致生产者线程使用enqueueBufferObj在向队列中添加新BufferObj时出错:
if (connObj->pendingSendHead == NULL) {//如果next显式初始化了,这个条件检测应该成立
connObj->pendingSendHead = connObj->pendingSendTail = bufferObj;
} else {//但是由于next没有显示初始化,导致pendingSendHead的值不是NULL,而是一个随机的,因此程序错误的运行到这里,出现上述错误
connObj->pendingSendTail->next = bufferObj;
connObj->pendingSendTail = bufferObj;
}
在简单的程序中,这中错误查找起来可能不是问题,但是如果程序很复杂,查找这种错误就会很浪费时间。因此,为了安全起见,以后对于C++中的结构体,类成员,在使用前,还是先进行初始化后为好。
C++中类成员使用前需要初始化的重要性的更多相关文章
- Java中类成员变量初始化顺序
一. 定义处默认初始化vs构造函数中初始化 java中类成员变量支持在声明处初始化,也可以在构造函数中初始化,那么这两者有什么区别呢?看下面例子 public class FieldsInit { p ...
- C++中类成员变量在初始化列表中的初始化顺序
引子:我们知道,C++中类成员变量的初始化顺序与其在类中的声明顺序是有关的. 先看代码: class TestClass1 { public: TestClass1() { cout << ...
- 读书笔记 effective c++ Item4 确保对象被使用前进行初始化
Item4 确保对象被使用前进行初始化 C++在对象的初始化上是变化无常的,例如看下面的例子: Int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: Cla ...
- C++ 成员函数前和函数后加const修饰符区别
博客转载自: https://www.iteblog.com/archives/214.html 分析以下一段程序,阐述成员函数后缀const 和 成员函数前const 的作用 #include< ...
- 【C++】const,static和static const类型成员变量声明及其初始化
1)const定义的常量在超出其作用域之后其空间会被释放,而static定义的静态常量在函数执行后不会释放其存储空间 void f1() { ; cout<<x<<endl; ...
- Delphi XE中类成员的访问权限(新增了strict private和strict protected,还有automated)
Delphi XE中类成员的访问权限共提供了6个关键词来用于限定访问权限:public.private.protected.published.automated strict private . s ...
- 读书笔记 effective c++ Item 4 确保对象被使用前进行初始化
C++在对象的初始化上是变化无常的,例如看下面的例子: int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证.看下面的例子: class Point { int x,y; ...
- 成员变量和成员函数前加static的作用?
成员变量和成员函数前加static的作用?答:它们被称为常成员变量和常成员函数,又称为类成员变量和类成员函数.分别用来反映类的状态.比如类成员变量可以用来统计类实例的数量,类成员函数负责这种统计的动作 ...
- Delphi字符串与字符数组之间的转换(初始化的重要性)
紧接着上篇博客讲解的内容: 将Char型数组转换为string类型还有下面的这种方法 但是我在测试的时候遇到了一些问题,并在下面进行了解释和总结 先说出我的总结 其实我们在学习编程的时候(比如我之前学 ...
随机推荐
- SpringMVC入门2-注解开发
Spring MVC 注解开发 <context:component-scan base-package="com.controls" /> Springmvc的扫描器 ...
- dnat,snat
Iptables实现NAT是最基本的功能,大部分家用路由都是基于其SNAT方式上网,使用Iptables实现外网DNAT也很简单,不过经常会出现不能正常NAT的现象. 以下命令将客户端访问1.,很多人 ...
- HDU Train Problem I 1022 栈模拟
题目大意: 给你一个n 代表有n列 火车, 第一个给你的一个字符串 代表即将进入到轨道上火车的编号顺序, 第二个字符串代表的是 火车出来之后到顺序, 分析一下就知道这,这个问题就是栈, 先进后出吗, ...
- 32位vs2010的项目如何在64位系统上运行
64位注册 1. 关闭Visual Studio.2. 在Visual Studio Tools目录,以管理员身份运行Visual Studio Command Prompt (2010),[注:这个 ...
- HDU_2147——组合博弈,转换为P/N图,然后找规律
Problem Description Recently kiki has nothing to do. While she is bored, an idea appears in his mind ...
- 关于C#泛型列表List<T>的基本用法总结
//示例代码如下:using System;using System.Collections.Generic;using System.Collections.ObjectModel;namespac ...
- SKViedoNode类
继承自 SKNode:UIResponder:NSObject 符合 NSCoding(SKNode)NSCopying(SKNode)NSObject(NSObject) 框架 /System/L ...
- BitBlt介绍
设备上下文画图有非常多种方法.比如通过创建位图画刷,利用其填充一个区域来实现图像的绘制.此外,还能够使用CDC类的位图函数来输出位图到设备上下文中. BitBlt 用于从原设备中复制位图到目标设备,语 ...
- uva 12253 - Simple Encryption(dfs)
题目链接:uva 12253 - Simple Encryption 题目大意:给定K1.求一个12位的K2,使得KK21=K2%1012 解题思路:按位枚举,不且借用用高速幂取模推断结果. #inc ...
- myeclipse快捷键收集整理
Ctrl+1 快速修复(最经典的快捷键,就不用多说了) Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Ctrl+Alt+↑ 复制当前行到上一行(复制增加) Alt ...