当前位置: 首页 > news >正文

学网站建设难不难网络平台制作方法

学网站建设难不难,网络平台制作方法,网站降权表现,个人做电商网站智能指针之shared_ptr与weak_ptr前言智能指针实例分析前言 C与其他语言的不同点之一就是可以直接操作内存#xff0c;这是一把双刃剑#xff0c;直接操作内存可以提高开发的灵活度#xff0c;开发人员在合适的时机申请内存#xff0c;在合适的时机释放内存#xff0c;减少… 智能指针之shared_ptr与weak_ptr前言智能指针实例分析前言 C与其他语言的不同点之一就是可以直接操作内存这是一把双刃剑直接操作内存可以提高开发的灵活度开发人员在合适的时机申请内存在合适的时机释放内存减少冗余内存的占用听起来非常不错。然而 实际情况是申请了内存忘记了释放导致内存泄漏又或者是申请了内存在某些情况下被释放了然而另一部分代码却在继续使用这块内存导致访问了非法内存程序崩溃。当然大部分的内存泄漏与访问非法内存导致的程序崩溃在debug版本中都是可以被发现的但是还是会存在一些比较隐秘的角落在测试期间发现不到导致用户在试用期间发生崩溃这是最糟的情况。 智能指针 C11的新特性之一就是增加了三组智能指针shared_ptr,weak_ptr,unique_ptr,通过合理的使用者三组智能指针可以极大的避免开发过程中有关内存的困扰。今天我们只介绍前两个。 shard_ptr是可以对引用进行计数的当有其他地方引用该指针时引用计数加1当有地方释放该指针时引用计数减一只有当引用计数未0时这个指针才会被真正的析构。 weak_ptr不会增加引用计数它一般是与shard_ptr搭配使用使用shared_ptr来构造weak_ptr,weak_ptr调用lock()方法如果该shared_ptr已经被析构了则返回null如果还没被析构则返回一个shared_ptr并且该shared_ptr的引用计数加1。 引用C的经典书籍 **《Effective C》**第三版中的一段话来感受下shared_ptr的优点 实际上返回shard_ptr让接口设计者得以阻止一大群客户犯下资源泄漏的错误因为就如条款14所言shard_ptr允许当前智能指针被建立起来时指定一个资源释放函数所谓删除其“deleter”绑定与智能指针身上。 shared_ptr有一个特别好的性质是它会自动使用它的每个指针专属的删除器因而消除另一个潜在的客户错误所谓的 “cross-DLL problem”。这个问题发生于“对象在动态链接程序库DLL中被new创建却在另一个DLL内被delete销毁“。在许多平台上这一类“跨DLL之new/delete成对运用”会导致运行期错误。 shared_ptr没有这个问题因为它缺省的删除器是来自shared_ptr诞生的那个DLL的delete。 在C开发中遇到的问题越多越会觉得**《Effective C》第三版**真是一本好书全书55个条款分为 让自己习惯C构造/析构/赋值运算资源管理设计与声明实现继承与面向对象设计模板与泛型编程定值new与delete杂项讨论 这九大部分每一项条款都直击问题要害给出防范措施搭配**《C Primer》**阅读C程序员必备 网上买**《Effective C》加一本《C Primer》大概要100块钱如果有需要的同学可以关注公众号程序员DeRozan**回复1207直接领取。 下面来通过一个实例来感受下智能指针。 实例分析 下面我们通过分析一个例子来大概感受下智能指针的好处。 一个服务会接收一个cmd以及其携带的参数并将其存入一个任务队列交给一个任务线程去处理。 worker是一个对象其有一个成员函数可以处理这个cmd。 函数asyncTaskHandler将这个cmd的handler函数以及参数封装到一个结构体中然后放入队列m_taskQue中会有任务线程来取任务并执行。 生产者 struct AICTask_t {int cmd;int task_id;taskStatus status;BaseWorker* worker;arg_t* arg; };int AICTaskManager::asyncTaskHandler(int cmd, std::string reqMsg, int reqMsgLen, std::string respMsg, int respMsgLen) {TdInfo(AICTaskManager::asyncTaskHandler);TdInfo(create task);AICTask_t task;auto iter m_workerMap.find(cmd); //m_workerMap : std::mapint, BaseWorker* if(iter ! m_workerMap.end()) {task-worker iter-second;task-arg.cmd cmd;task-arg.reqMsg reqMsg;task-arg.reqMsgLen reqMsgLen;task-arg.respMsg respMsg;task-arg.respMsgLen respMsgLen;task-status prepare_to_start;}else{TdError(not found this cmd);return -1;}pthread_mutex_lock(m_workerLock);while (m_taskQue.size() m_maxQueSize !m_stop){pthread_cond_wait(m_cond_not_full, m_workerLock);}m_taskQue.push(task); //std::queueAICTask_t* m_taskQue;m_taskMap[m_task_id] task;m_task_id;pthread_mutex_unlock(m_workerLock);pthread_cond_broadcast(m_cond_not_empty);TdInfo(insert a task to queue);return 0; }aicThreadHandle是任务线程的线程入口函数负责将handler以及参数拿到并执行。 消费者 void *AICTaskManager::aicThreadHandle(void *arg) {if(!arg) {TdError(bad parameter);return nullptr;}AICTaskManager *taskManager (AICTaskManager *)arg;pthread_mutex_lock(taskManager-m_workerLock);//loop for get task,every get lock, can get task while(true){// if m_taskQue not empty, get task, if empty, wait to get task// when task queue not empty, only one creater will wake up condition.while (taskManager-m_taskQue.empty() !taskManager-m_stop){TdDebug(waiting to wake up);pthread_cond_wait(taskManager-m_cond_not_empty, taskManager-m_workerLock);// m_cond was waked up and get lock}//step while, now m_taskQue not emptyif (taskManager-m_stop){pthread_mutex_unlock(taskManager-m_workerLock);TdInfo(thread % exit, pthread_self());pthread_exit(NULL);}AICTask_t* task taskManager-m_taskQue.front();taskManager-m_taskQue.pop();pthread_mutex_unlock(taskManager-m_workerLock);pthread_cond_broadcast(taskManager-m_cond_not_full);TdInfo(exec function);task-status running;(task-worker-handleCommand)(task-arg-cmd, task-arg-reqMsg, task-arg-reqMsgLen, task-arg-respMsg, task-arg-respMsgLen);task-status over;}return nullptr; }上述代码的逻辑很简单简单的 生产者消费者模式动态申请的内存全部使用的裸指针来保存而且这个代码中有一个很明显的错误。 生产者代码的第13行AICTask_t task是在栈上申请的变量存入std::queueAICTask_t* m_taskQue m_taskQue内保存的是指针类型所以在第34行通过取地址符传入了一个指针指向栈上的task结果程序在消费者的第41行崩溃了。 为什么会崩溃呢原因就是生产者把指向task的指针放入任务队列后函数就执行结束了task是栈上的变量随着程序结束就被释放了然而m_taskQue还保存着指向task的指针指向了一块未初始化的内存。在任务处理函数中这个指针被访问了程序就崩溃了。 为什么不在堆上申请task呢因为我觉得在堆上申请还需要手动释放容易出问题所以想偷个懒直接在栈上申请了没有考虑到上面说的问题。 消费者的代码中对于裸指针都是直接访问的也没有检查是不是已经被释放了。 总之手动管理内存实在太容易出问题了所以使用智能指针来管理内存是很不错的选择。 将上面的代码进行改造将需要用到指针的地方改为shared_ptr,并使用weak_ptr来检查智能指针已经被析构。 改造过后 生产者 int AICTaskManager::asyncTaskHandler(int cmd, std::string reqMsg, int reqMsgLen, std::string respMsg, int respMsgLen) {TdInfo(AICTaskManager::asyncTaskHandler);TdInfo(create task);std::shared_ptrAICTask_t task std::make_sharedAICTask_t();auto iter m_workerMap.find(cmd);if(iter ! m_workerMap.end()) {task-worker iter-second;task-arg.cmd cmd;task-arg.reqMsg reqMsg;task-arg.reqMsgLen reqMsgLen;task-arg.respMsg respMsg;task-arg.respMsgLen respMsgLen;task-status prepare_to_start;}else{TdError(not found this cmd);return -1;}pthread_mutex_lock(m_workerLock);while (m_taskQue.size() m_maxQueSize !m_stop){pthread_cond_wait(m_cond_not_full, m_workerLock);}m_taskQue.push(task);m_taskMap[m_task_id] task;m_task_id;pthread_mutex_unlock(m_workerLock);pthread_cond_broadcast(m_cond_not_empty);TdInfo(insert a task to queue);return 0; }消费者 void *AICTaskManager::aicThreadHandle(void *arg) {if(!arg) {TdError(bad parameter);return nullptr;}AICTaskManager *taskManager (AICTaskManager *)arg;pthread_mutex_lock(taskManager-m_workerLock);//loop for get task,every get lock, can get task while(true){// if m_taskQue not empty, get task, if empty, wait to get task// when task queue not empty, only one creater will wake up condition.while (taskManager-m_taskQue.empty() !taskManager-m_stop){TdDebug(waiting to wake up);pthread_cond_wait(taskManager-m_cond_not_empty, taskManager-m_workerLock);// m_cond was waked up and get lock}//step while, now m_taskQue not emptyif (taskManager-m_stop){pthread_mutex_unlock(taskManager-m_workerLock);TdInfo(thread % exit, pthread_self());pthread_exit(NULL);}// std::weak_ptrAICTask_t task taskManager-m_taskQue.front();std::shared_ptrAICTask_t task std::weak_ptrAICTask_t(taskManager-m_taskQue.front()).lock();if(!task){TdError(expired task);return nullptr;}taskManager-m_taskQue.pop();pthread_mutex_unlock(taskManager-m_workerLock);pthread_cond_broadcast(taskManager-m_cond_not_full);TdInfo(exec function);task-status running;std::shared_ptrBaseWorker worker std::weak_ptrBaseWorker(task-worker).lock();if (!worker){TdError(worker expired);return nullptr;}(worker-handleCommand)(task-arg.cmd, task-arg.reqMsg, task-arg.reqMsgLen, task-arg.respMsg, task-arg.respMsgLen);task-status over;}return nullptr; }这样我们在使用shared_ptr前先通过weak_ptr判断是够可用然后使用完成后该指针会自动将引用计数减一等到引用计数未0也就是没有任何地方再引用它就可以释放它指向的那块内存了。 不过需要注意的是shard_ptr一定要用make_shared来构造虽然有时携程shared_ptrT(new T())也能通过编译但是这是会导致内存泄漏的。 智能指针的用法非常多本文讲的是最常见的一种情况其他更复杂的用法则需要继续学习与发现。
http://www.sczhlp.com/news/159271/

相关文章:

  • 长春建站怎么做网络货运平台有哪些
  • 免费网站制作 优帮云做网站会什么问题
  • 深圳企业公司做网站wordpress怎么在文章中做一个单词链接到本文章中的一段文字
  • 网站搭建申请python网站开发高并发
  • 韩国儿童才艺网站建设模板建设银行积分商城网站
  • 网站页面制作公司外贸营销方式有哪些
  • 网站建设及维护流程合肥市住房建设局网站
  • 装饰网站卧室做炕百度高新公司网站建设哪家好
  • 企业网站布局长沙做网站排名
  • 企业网站的建设论文上海百度推广开户
  • 开发网站要注意什么北京城建建设工程有限公司网站
  • 简单大气食品农业网站源码好看云在线网站模板
  • 做兼职上什么网站找机关门户网站建设要求
  • 宿州高端网站建设公司成都私人网站制作公司
  • 购物分享网站模板河南省罗山县做网站的公司
  • 南宁上林网站建设网站排名方法
  • 天津手机网站公司建网方案策划书
  • 怎么做卖保险的网站可以安装wordpress
  • seo优化网站源码国内免费saas+crm
  • 公众号链接电影网站怎么做网站开发前如何配置电脑
  • 招商网站如何做推广服务号 订阅号
  • 做产地证网站泰安的网站建设公司
  • 字画网站建设柒比贰Wordpress
  • 建筑公司网站起名上海建设部网站
  • 遂宁市城市建设档案馆网站郑州网站搜索排名
  • 网站标题格式秦皇岛做网站的公司选汉狮
  • 永仁县建设工程信息网站帮人网站开发维护违法
  • 太原网站建设开发wordpress相关文章代码
  • 怎样免费设计网站建设联想电脑网站建设策划书
  • seo公司网站云开发cms内容管理系统