detach()之大坑:detach会引起局部变量失效引起线程对内存的非法访问题。
detach()之大坑:detach会引起局部变量失效引起线程对内存的非法访问题。
一:传递临时对象作为线程参数
(1.1)要避免的陷阱(解释一)
(1.2)要避免的陷阱(解释一)
事实一:只要用临时构造的A类对象作为参数传递给线程,那么就一定能够在主线程(main函数)执行完毕之前把线程函数的第二个参数构建出来,从而确保即便detach了,子线程也能够安全运行。
总结1:若传递int这种简单类型参数,加你都是值传递,不要用引用,防止节外生枝。
总结2:如果传递类对象,要避免隐式类型转换。应该全部在创建线程这一行的时候构建临时对象出来,然后再线程函数参数里用引用来接,否则系统还会构造一个对象,总共会构造三个对象,所以thread里面的运行第很暴力的。
结论3:建议不使用detach,只是用join,那么就不存在局部变量失效引起其他线程对内存非法访问的问题。
应该像下面这样写:
class A
{
public:
int m_i;
//转换类型构造哈函数,可以把一个int转换成一个A类对象
A(int i) :m_i(i) { cout<<"执行构造函数"<<endl; }
A(const A &may) :m_i(may.m_i) { cout<<"执行拷贝构造函数"<<endl; }
~A() { cout<<"执行析构函数"<<endl; }
};
void myprint(const int i, const A &my)//一定要用引用来接,如果不用引用来接,会生成三个临时对象,造成系统资源的浪费
{
cout << my.m_i << endl;
cout << i << endl;
return;
}
int mian()
{
int x = 2;//若传递int这种简单类型参数,加你都是值传递,不要用引用,防止节外生枝。
int y = 9;
thread mythread(myprint, x, A(y));// A(y)这里生成一个局部对象(可以防止局部变量失效引起其他线程对内存非法访问的问题)
mythread.join(); //但是这里会调用拷贝构造函数,所以会生成两个临时对象。
//mythread.detach();
cout << "主线程即将执行结束" << endl;
return 0;
}
注意:一个简单的类型变量作为引用参数创建一个线程的时候,其实不是对这个局部变量的引用,这里其实是拷贝,即生成了一个副本,
所以用detach主线程结束系统回收局部变量后不会引起局部变量在其他线程中非法引用的问题。
二:传递临时对象作为线程参数(继续)(测试大法:发现一些比较神奇的蛛丝马迹)
2.1线程id概念:id是一个数字,每个线程(不管是主线程还是子线程)实际上都对应一个数字,而且每个线程对应的这个数字是不相同的,也就是说不同的线程,它的线程id(数字)必然是不相同的。线程id可以用c++标准库里的函数来获取,
即就是:std::this_thread::get_id()来获取。
2.2临时对象构造时机捕获:
class A
{
public:
int m_i;
//转换类型构造哈函数,可以把一个int转换成一个A类对象
A(int i) :m_i(i) { cout<<"执行构造函数"<<this<<"threadid:"<<std::this_thread::get_id()<<endl; }
A(const A &may) :m_i(may.m_i) { cout<<"执行拷贝构造函数"<<this<<"threadid:"<<std::this_thread::get_id()<<endl;}
~A() { cout<<"执行析构函数"<<this<<"threadid:"<<std::this_thread::get_id()<<endl; }
};
void myprint2(const A &my)//一定要用引用来接,如果不用引用来接,会生成三个临时对象,造成系统资源的浪费
{
cout<<"子线程的参数地址是:"<<&my<<"threadid:"<<std::this_thread::get_id()<<endl;
}
int mian()
{
cout<<"主线程的id:"<<std::this_thread::get_id()<<endl;
int y = 2;//若传递int这种简单类型参数,加你都是值传递,不要用引用,防止节外生枝。
thread mythread(myprint, A(y));// A(y)这里生成一个局部对象,在主线程中生成这个临时对象,所以不用担心detach的问题(可以防止局部变量失效引起其他线程对内存非法访问的问题),但是这里会调用拷贝构造函数,所以会生成两个临时对象。
//thread mythread(myprint, y) //这里生成的临时对象是在子线程中生成的,所有可能会引起主线程结束之后子线程对内存的非法访问问题。
mythread.join();
//mythread.detach();
cout << "主线程即将执行结束" << endl;
return 0;
}
detach()之大坑:detach会引起局部变量失效引起线程对内存的非法访问题。的更多相关文章
- detach() 使用和.detach()和.data的区别 、cpu()函数的作用
detach() 使用和.detach()和.data的区别 .cpu()函数的作用 待办 detach使用 https://blog.csdn.net/qq_27825451/article/det ...
- muParser公式库使用简介( 转)
muParser是一个跨平台的公式解析库,它可以自定义多参数函数,自定义常量.变量及一元前缀.后缀操作符,二元操作符等,它将公式编译成字节码,所以计算起来非常快. 当前版本V1.28,官方网址http ...
- Jquery empty() remove() detach() 方法的区别
方法简介: empty() This method removes not only child (and other descendant) elements, but also any text ...
- 转载JQuery 中empty, remove 和 detach的区别
转载 http://www.cnblogs.com/lisongy/p/4109420.html .empty() 描述: 从DOM中移除集合中匹配元素的所有子节点. 这个方法不接受任何参数. 这个 ...
- VC中的Attach和Detach
CWnd,CDC, Cxxx等都是MFC的类,这些类提供了很多成员函数来执行系统调用等操作,但是核心的类成员数据都是 句柄,(包括窗口句柄,DC句柄,线程句柄等). m_hWnd m_hDC m ...
- jQuery中删除方法empty(),remove()和detach()的区别
empty():清空匹配的元素集合中所有的子节点,自身节点和事件都未被删除. remove():这个方法不会把匹配的元素从jQuery对象中删除,因而可以在将来再使用这些匹配的元素.但除了这个元素本身 ...
- 探索jquery方法中empty,remove与detach的区别
最近一直疑惑此三种方法的具体区别在于何处,随即想弄明白其具体的区别,看了一些说明,也依照官方文档,终于把这三个方法弄明白了,果然功夫不负有心人,继续努力. 上正文,先简单介绍下这三种方法 .empty ...
- 揭秘 Kubernetes attach/detach controller 逻辑漏洞致使 pod 启动失败
前言 本文主要通过深入学习k8s attach/detach controller源码,了解现网案例发现的attach/detach controller bug发生的原委,并给出解决方案. 看完本文 ...
- pytorch训练GAN时的detach()
我最近在学使用Pytorch写GAN代码,发现有些代码在训练部分细节有略微不同,其中有的人用到了detach()函数截断梯度流,有的人没用detch(),取而代之的是在损失函数在反向传播过程中将bac ...
随机推荐
- 【代码笔记】Java常识性基础补充(二)——数组、ArrayList集合、ASCII编码、 eclipse基础操作、eclipse调试、eclipse项目导入、eclipse快捷键
1.0 如何定义数组以及访问数组中的元素,如下所示.ArrayDemo01.java public class ArrayDemo01 { public static void main(String ...
- 1-4 Sass的基本特性-基础
[Sass]声明变量 定义变量的语法: 在有些编程语言中(如,JavaScript)声明变量都是使用关键词“var”开头,但是在 Sass 不使用这个关键词,而是使用大家都喜欢的美元符号“$”开头.我 ...
- php 环境搭配 脚本模式(1)
php介绍目标1:<?phpecho 'hello world'; //配置好了apacheecho '<br/> 现在时间:" .date(’Y-m-d H:i:s‘)“ ...
- CSS布局之传统方法
传统的页面布局依赖于盒模型+流动模型(flow)+浮动模型(float)+层模型(layer)来实现页面的布局,具体方法是通过盒模型+display属性+float属性+position属性来加以实现 ...
- 程序员装B指南(转载)
转自:http://www.oschina.net/question/615783_115390 一.准备工作 "工欲善其事必先利其器." 1.电脑不一定要配置高,但是双屏是必须的 ...
- Windows下将jar包封装成服务程序
1 准备 使用工具Procrun(http://commons.apache.org/proper/commons-daemon/procrun.html),下载地址(http://archive.a ...
- phantomjs rendering
http://wwwy3y3.ghost.io/pageres-phantomjs-capture-sreenshot-chinese-fonts-not-render-correctly/ 在使用中 ...
- SQL Server ->> SQL Server 2016功能改进之 -- Update Statistics
1) 以前SQL Server更新一张表/索引的间隔是固定的,创建时更新一次,到了500行时更新第二次,接下来就是呈百分比式的间隔去更新,距离数据修改量达到表的行数量的的20%再次触发更新.但是这样的 ...
- NS Simulation: Scheduling Events (examples inside)
NS Simulation: Scheduling Events Simulation time A similation system (such as NS) must have a built- ...
- MySQL5.7的组提交与并行复制
从MySQL5.5版本以后,开始引入并行复制的机制,是MySQL的一个非常重要的特性. MySQL5.6开始支持以schema为维度的并行复制,即如果binlog row event操作的是不同的sc ...