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类型还有下面的这种方法 但是我在测试的时候遇到了一些问题,并在下面进行了解释和总结 先说出我的总结 其实我们在学习编程的时候(比如我之前学 ...
随机推荐
- javascript note
boolean("false") =====>true Date(1387123200000)不等于new Date(1387123200000) 用Date(1387123 ...
- 【二分】Codeforces 706B Interesting drink
题目链接: http://codeforces.com/problemset/problem/706/B 题目大意: n (1 ≤ n ≤ 100 000)个商店卖一个东西,每个商店的价格Ai,你有m ...
- LinGo:装货问题——线性规划,整数规划,1988年美国数模B题
7种规格的包装箱要装有两辆铁路平板车上去,包装箱的宽和高相同,但厚度(t,以cm计)和重量(以kg计)不同, 表A-1给出了每包装箱的厚度.重量和数量,每辆车有10.2m长的地方用来装包装箱(像面包片 ...
- Matlab:回归分析(1)
1.多元线性回归 %数据的输入 x = [ ]; y = [ ]; %转换为列向量 X = [ones(,) x']; Y = y'; %回归分析及检验 [b, bint, r, rint, stat ...
- 在vim下写python 会出现python错误:unexpected unident
需要在.vimrc 的set tabstop=4的这一行上面增加 set expandtab 否则会报unexpected unident
- C++获得系统路径
源码: [cpp] view plaincopy #include <Shlobj.h> #include <stdio.h> #include <locale.h> ...
- C++[类设计] ini配置文件读写类config
//in Config.h #pragma once #include <windows.h> #include <shlwapi.h> #pragma comment(l ...
- Windows下用C语言获取进程cpu使用率,内存使用,IO情况
#ifndef PROCESS_STAT_H #define PROCESS_STAT_H #ifdef __cplusplus extern “C” { #endif typedef l ...
- http to https automatic--weblogic/jboss/tomcat--reference
weblogic reference from:http://middlewaremagic.com/weblogic/?p=2019 Many times we want to secure our ...
- 跨平台传输中使用base64来保证非ascii码字符串的完整性
首先,我们来看一个例子: byte[] b=new byte[]{2,9,43}; String ss=new String(b,"utf-8"); byte[] b1=ss.ge ...