线程内存释放问题


在按键中新建线程如下:

HANDLE hThread=CreateThread(NULL,0,RunProc,(LPVOID)&m_PtrArray,0,NULL);
CloseHandle(hThread);


静态函数如下:

DWORD WINAPI CMyView::RunProc(LPVOID lpParameter)
{

CPtrArray *Lpray;
Lpray=(CPtrArray*)lpParameter;

/*
read lpray data
第一次读lpray时没问题,
*/

}


1,此程序在第一次按建时没问题,多几次就好象数据会出错这是为何?如解决?

2,为什么有人会在线程中delete lpParameter?如果我也想释放代码该如何写?

3,在按键中新建新程会有问题吗?应该写在哪里?(要用按键触发线程)

新手,大神勿喷

20 个解决方案

#1


1. 线程开始运行和结束的时间都不能预测
2. 保证在线程运行过程中使用的内存不能被其他地方销毁,如果使用公用变量应该注意同步
所以问题
1.  多次运行的时候,可能同时存在多个线程,会不会因为同步没有做好,或者其他地方删除了m_PtrArray中的内容,可是线程还可能在使用,可用CRITICAL_SECTION避免问题
2. 在线程里面delete需要保证这个指针只有这个线程在用
可以这样写
CPtrArray* pArrayForThread = new CPtrArray;
//复制内容
//启动线程

线程用完了之后就可以delete。因为每次这个新内存都存在,并且线程不用了才会销毁

3. 在什么地方新建线程都可以,注意同步

#2


引用 1 楼 piaobotudou 的回复:
1. 线程开始运行和结束的时间都不能预测
2. 保证在线程运行过程中使用的内存不能被其他地方销毁,如果使用公用变量应该注意同步
所以问题
1.  多次运行的时候,可能同时存在多个线程,会不会因为同步没有做好,或者其他地方删除了m_PtrArray中的内容,可是线程还可能在使用,可用CRITICAL_SECTION避免问题
2. 在线程里面delete需要保证这个指针只有这个线程在用
可以这样写
CPtrArray* pArrayForThread = new CPtrArray;
//复制内容
//启动线程

线程用完了之后就可以delete。因为每次这个新内存都存在,并且线程不用了才会销毁

3. 在什么地方新建线程都可以,注意同步



1,我现在主要想知道这时 在线程里去读 Lpray 时面的数据会不会出错?(没有在别的地方修改m_PtrArray,也不在线程结束之前按下按键)

2,delete lpParameter的代码怎么写?我直接这样写会出错。

#3


m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.

#4


引用 3 楼 91program 的回复:
m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.


是new 出来的,我想知道怎么 delete lpParameter?为什么要这样做?求赐教

#5


CPtrArray *Lpray;
Lpray=(CPtrArray*)lpParameter;
delete Lpary;

#6


引用 3 楼 91program 的回复:
m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.


是成员变量,不是new出来的,但它指向的数据是new出来的,这样可以 delete吗?

#7


我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因

#8


在你上个贴装,你结完分后,我给你代码了,释放m_PtrArray中new出来的内存。
而且,你m_PtrArray不是new出来的吧,m_PtrArray数组里面的每个指针是你new出来的。

你delete lpParameter它干嘛,lpParameter只是你传进来的指针,该指针指向m_PtrArray对象。
具体你应该释放m_PtrArray中你new出来的东西。

第一个问题,你在按键中,开启线程,你多按几次,就多开启了线程,线程里处理的数据实际
是m_PtrArray中的数据,你多按几次,多个线程处理同一个内存中的数据,就会有问题,需要线程同步。

第二个问题,上面说了。

第三个问题,放按键中,没问题,看你的流程怎么使用,如果有需要,在别的地方也可以。

#9


引用 7 楼 takpod 的回复:
我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因

贴你线程中的代码吧

#10


引用 9 楼 fqzlala 的回复:
Quote: 引用 7 楼 takpod 的回复:

我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因

贴你线程中的代码吧



好吧!我发觉可能我的数据没有出错,是电机控制卡运运时出了错。

#11



DWORD WINAPI CMyView::RunProc(LPVOID lpParameter)
{
CPtrArray *Lpray;
Lpray=(CPtrArray*)lpParameter; //数据
unsigned short AxisArray[2]; //X轴和y轴
long Target[2],Cen[2]; //目标点 和 圆弧的圆心
long start_speed,move_speed,pos_x,pos_y,cen_x,cen_y,turn_clkwise;
move_speed=10000; //运得速度
start_speed=(move_speed/2); //起始速度
AxisArray[0]=AIX0; //轴号0
AxisArray[1]=AIX1; //轴号1
d5400_set_vector_profile(start_speed,move_speed,ACC_TIME,DEC_TIME);//设置电机插补速度
pos_x=((CGraph *)Lpray->GetAt(0))->m_StartPt.x; //得到第一点的坐标
pos_y=((CGraph *)Lpray->GetAt(0))->m_StartPt.y; //
d5400_t_line2(AIX0,pos_x,AIX1,pos_y,ABSOL); //直线移动到第一点(走直线)
while((M_TURN==d5400_check_done(AIX0))||(M_TURN==d5400_check_done(AIX1)))//等待到位
{}
//============================================================================

for (int i=0;i<(int)((CGraph *)Lpray->GetSize());i++)
{
if (1==((CGraph *)Lpray->GetAt(i))->m_Type)//这是直线
{
pos_x=((CGraph *)Lpray->GetAt(i))->m_EndPt.x;
pos_y=((CGraph *)Lpray->GetAt(i))->m_EndPt.y;
d5400_t_line2(AIX0,pos_x,AIX1,pos_y,ABSOL);//启动走直线

else //这是圆弧
{
pos_x=((CGraph *)Lpray->GetAt(i))->m_EndPt.x;
pos_y=((CGraph *)Lpray->GetAt(i))->m_EndPt.y;
cen_x=((CGraph *)Lpray->GetAt(i))->m_ArcCenPt.x;
cen_y=((CGraph *)Lpray->GetAt(i))->m_ArcCenPt.y;
if (0==((CGraph *)Lpray->GetAt(i))->m_TurnFactor)
{turn_clkwise=ATCW;} //顺时针
else
{turn_clkwise=CLWI;} //逆时针
Target[0]=pos_x;
Target[1]=pos_y;
Cen[0]=cen_x;
Cen[1]=cen_y;
d5400_arc_move(AxisArray,Target,Cen,(WORD)turn_clkwise);//启动走圆弧
}
while((M_TURN==d5400_check_done(AIX0))||(M_TURN==d5400_check_done(AIX1)))//等待到位
{}
}

return 0;
}

#12


1.你用的雷塞的运动控制卡
我猜的,就当我吹牛B,我能看得出来,因为我用过其他型号的卡。

2.CGraph类是你们自己写的类,就是让机器如何运动,和运动的坐标
你初始化m_PtrArray时,new出来的CGraph对象,记录了不同的运动轨迹。
CGraph对象跟你这个线程里的操作没有关系,只要在程序退出前释放掉就好。
在线程中,你只是读取这个对象中相关的运动数据,保证运动到位。只要你没
改动过这些数据,使用的时候就不会出错。

3.你具体出现了什么问题,如果是线程开启执行了,出现程序报错问题,崩溃
或者其他什么,你就需要设置断点,进行跟进,看看是不是哪个变量用错了,
或者是哪个变量的数据不对。

4.你第一次使用该线程时,运动控制不进行复位操作吗,至少知道目前XY轴的起始点
在哪,也就是0点在哪,运动控制卡才能计算坐标,给电机发送相应的脉冲。
那你第二次点击按键运行的时候,这个时候XY轴的坐标是多少呢?
我猜你的问题是,多运行几次,就运行的不准确,更严重的情况是碰撞到极限。

5.在你点击按键运行时,也就是线程运行时,你再次点击,这就会出错。上个线程还没有
运行完,你就要又运行,又要访问数据,又给XY轴发命令,这肯定会混乱。必须控制,防止在
线程没运行完,又再次运行。

6.你线程最后已经return 0了,线程内你使用的变量内存,线程会自动回收,如果你在线程内new
了变量出来,你就需要自己释放,线程不管释放。你线程外new出来的,还是在线程外释放吧。这个
跟你贴子的内容没什么关系,我之前回答过你delete lpParameter的问题。

#13


你们公司是做什么行业的?在什么地方?咱们有相同的东西,可以多参考

#14


多线程不能同时修改一个数据或操作一个设备
起码四年前我用DMC5400的时候,它没有做线程安全,如果不在每一个d5400_XXX前后都加上线程锁,就会不知什么时候卡死

#15


引用 13 楼 fqzlala 的回复:
你们公司是做什么行业的?在什么地方?咱们有相同的东西,可以多参考




1,对!用的就是雷塞的运动控制卡


2,也对!我没有改过数据,运动过程中更不可能去改数据,
只是在m_PtrArray初始化之后排了一下序。如下
	CGraph *tem_pGraph;
for(int j=0;j<(m_PtrArray.GetSize()-1);j++)
{
for(int i=0;i<((m_PtrArray.GetSize()-1)-j);i++)
{
if((((CGraph *)m_PtrArray.GetAt(i))->m_SerialNo)>(((CGraph *)m_PtrArray.GetAt(i+1))->m_SerialNo))
{
tem_pGraph=(CGraph *)m_PtrArray.GetAt(i);
m_PtrArray.SetAt(i,(CGraph *)m_PtrArray.GetAt(i+1));
m_PtrArray.SetAt(i+1,tem_pGraph);
}
}
}
((CGraph *)m_PtrArray.GetAt(0))->Draw(1);
*/


3,我写这个程序只是为了测试一下我传进来的m_PtrArray有没有正确,
我在线程里写了个死循环,读位置画图形如下(红色是电机轨迹),运行几分钟后发觉图形会出错有时候会卡死(跑一圈10秒左右),有时出错之后的下一圈又变正确了,所以我觉得是控制卡函数调用的问题。准备问客服


 

 线

4,我没有接电机(怕撞),只是在工控机上读位置画图,运行前复位,更不可能在运行过程中再启动建立线程。

5,上面回答

6,线程内不new,线程外new的那个线程外释放。

我想说:

一,我之前在深圳工作,现在在东莞,是自动化行业,我同学做机器视觉和这间公司合作项目,公司想自己搞上位机,我同学就介绍我进来,公司有很多plc的,我是第一个搞vc的,进公司第50天,苦逼。

二,如果能指导一下,真的万分感激,如果我有什么能帮上忙的我一定尽力!

三,感谢,感谢,感谢!

#16


我最想清楚的是 是转进来的数据出错 还是 控制卡出错, 不过现在测试的结果好像是 控制卡出错,如果是真的就只能问客服怎么用 控制卡了,

#17


你传进去的数据应该都是对的吧,说白了,就是点到点运动,也就是坐标,你看你数据里的坐标都对了,
基本也就对了,然后是圆弧还是直线,这个属性就很难错了,排序,不会影响数据的。

你现在不是就在模拟运动控制么,也没接电机,要验证数据,线程里没必要调用运动控制卡函数,你就模拟在
界面上一个区域内画图就行了,不用无限循环读数据画图,画一遍就知道你的数据对不对了。

照上面,你验证你的数据对不对之后,再验证控制卡。你现在画图是从卡里读取的位置画的图,那你在线程里,
每次发运动命令时,都用读到的运动卡里的位置,跟你的数据进行一次校验,建议用断点跟吧,一次就能发现
问题的,到底是哪发错了。而且你说的假死,不是有无限等待运动到位的那个吗,可能是那个地方出现的问题,
卡不认为运动到位,你就无限等待,所以假死。

还有,雷塞的卡,有的卡,对插补支持不好,圆弧我不知道。你最好问客服确认下,尤其是他们技术开发这卡的
人,我以前问过他们的人,有的告诉我有的卡S型曲线不太好呢。

还有点注意,就是相对坐标和绝对坐标问题了,两种计算方式不一样,我的经验是用相对坐标模式,调用运动控制
卡函数时是按照绝对坐标计算的思路,计算出相对的脉冲数,给函数提供参数的,这样电机运动更精准,函数模式
设置的是相对坐标模式。

到这我就帮不了你什么了,具体看你自己调试程序吧,我是做SMT行业的,没用到圆弧,就是T型S型曲线,直线
插补等等。没你们那么复杂。

#18


我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?

#19


引用 18 楼 takpod 的回复:
我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?

你开始的数据,就排个序,又没改动,怎么会错,如果错就奇怪了。

#20


引用 19 楼 fqzlala 的回复:
Quote: 引用 18 楼 takpod 的回复:

我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?

你开始的数据,就排个序,又没改动,怎么会错,如果错就奇怪了。

嗯~多谢了!感谢

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: