线程内存释放问题

takpod 2014-06-10 03:34:59
在按键中新建线程如下:

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,在按键中新建新程会有问题吗?应该写在哪里?(要用按键触发线程)

新手,大神勿喷
...全文
327 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
takpod 2014-06-12
  • 打赏
  • 举报
回复
引用 19 楼 fqzlala 的回复:
[quote=引用 18 楼 takpod 的回复:] 我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?
你开始的数据,就排个序,又没改动,怎么会错,如果错就奇怪了。[/quote] 嗯~多谢了!感谢
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
你们公司是做什么行业的?在什么地方?咱们有相同的东西,可以多参考
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
1.你用的雷塞的运动控制卡 我猜的,就当我吹牛B,我能看得出来,因为我用过其他型号的卡。 2.CGraph类是你们自己写的类,就是让机器如何运动,和运动的坐标 你初始化m_PtrArray时,new出来的CGraph对象,记录了不同的运动轨迹。 CGraph对象跟你这个线程里的操作没有关系,只要在程序退出前释放掉就好。 在线程中,你只是读取这个对象中相关的运动数据,保证运动到位。只要你没 改动过这些数据,使用的时候就不会出错。 3.你具体出现了什么问题,如果是线程开启执行了,出现程序报错问题,崩溃 或者其他什么,你就需要设置断点,进行跟进,看看是不是哪个变量用错了, 或者是哪个变量的数据不对。 4.你第一次使用该线程时,运动控制不进行复位操作吗,至少知道目前XY轴的起始点 在哪,也就是0点在哪,运动控制卡才能计算坐标,给电机发送相应的脉冲。 那你第二次点击按键运行的时候,这个时候XY轴的坐标是多少呢? 我猜你的问题是,多运行几次,就运行的不准确,更严重的情况是碰撞到极限。 5.在你点击按键运行时,也就是线程运行时,你再次点击,这就会出错。上个线程还没有 运行完,你就要又运行,又要访问数据,又给XY轴发命令,这肯定会混乱。必须控制,防止在 线程没运行完,又再次运行。 6.你线程最后已经return 0了,线程内你使用的变量内存,线程会自动回收,如果你在线程内new 了变量出来,你就需要自己释放,线程不管释放。你线程外new出来的,还是在线程外释放吧。这个 跟你贴子的内容没什么关系,我之前回答过你delete lpParameter的问题。
takpod 2014-06-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;
}
takpod 2014-06-11
  • 打赏
  • 举报
回复
引用 9 楼 fqzlala 的回复:
[quote=引用 7 楼 takpod 的回复:] 我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因
贴你线程中的代码吧[/quote] 好吧!我发觉可能我的数据没有出错,是电机控制卡运运时出了错。
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
引用 7 楼 takpod 的回复:
我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因
贴你线程中的代码吧
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
在你上个贴装,你结完分后,我给你代码了,释放m_PtrArray中new出来的内存。 而且,你m_PtrArray不是new出来的吧,m_PtrArray数组里面的每个指针是你new出来的。 你delete lpParameter它干嘛,lpParameter只是你传进来的指针,该指针指向m_PtrArray对象。 具体你应该释放m_PtrArray中你new出来的东西。 第一个问题,你在按键中,开启线程,你多按几次,就多开启了线程,线程里处理的数据实际 是m_PtrArray中的数据,你多按几次,多个线程处理同一个内存中的数据,就会有问题,需要线程同步。 第二个问题,上面说了。 第三个问题,放按键中,没问题,看你的流程怎么使用,如果有需要,在别的地方也可以。
takpod 2014-06-11
  • 打赏
  • 举报
回复
我现在问题是,当程序进入线程进行无限循环时会出错,有可能是lpray的数据出错,也有可能是硬件出错,我现在想找出原因
takpod 2014-06-11
  • 打赏
  • 举报
回复
引用 3 楼 91program 的回复:
m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.
是成员变量,不是new出来的,但它指向的数据是new出来的,这样可以 delete吗?
微型蚂蚁 2014-06-11
  • 打赏
  • 举报
回复
CPtrArray *Lpray; Lpray=(CPtrArray*)lpParameter; delete Lpary;
takpod 2014-06-11
  • 打赏
  • 举报
回复
引用 3 楼 91program 的回复:
m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.
是new 出来的,我想知道怎么 delete lpParameter?为什么要这样做?求赐教
91program 2014-06-11
  • 打赏
  • 举报
回复
m_PtrArray 是 new 来的吗?如果不是,就不能 delete。就算是 new 来的,最好是在 new 的进程/线程中 delete.
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
引用 18 楼 takpod 的回复:
我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?
你开始的数据,就排个序,又没改动,怎么会错,如果错就奇怪了。
takpod 2014-06-11
  • 打赏
  • 举报
回复
我的程序是运行很多次之后才出错的,一般运行一两次不会出错,你是不是也觉得数据没错?
肆水東澤 2014-06-11
  • 打赏
  • 举报
回复
你传进去的数据应该都是对的吧,说白了,就是点到点运动,也就是坐标,你看你数据里的坐标都对了, 基本也就对了,然后是圆弧还是直线,这个属性就很难错了,排序,不会影响数据的。 你现在不是就在模拟运动控制么,也没接电机,要验证数据,线程里没必要调用运动控制卡函数,你就模拟在 界面上一个区域内画图就行了,不用无限循环读数据画图,画一遍就知道你的数据对不对了。 照上面,你验证你的数据对不对之后,再验证控制卡。你现在画图是从卡里读取的位置画的图,那你在线程里, 每次发运动命令时,都用读到的运动卡里的位置,跟你的数据进行一次校验,建议用断点跟吧,一次就能发现 问题的,到底是哪发错了。而且你说的假死,不是有无限等待运动到位的那个吗,可能是那个地方出现的问题, 卡不认为运动到位,你就无限等待,所以假死。 还有,雷塞的卡,有的卡,对插补支持不好,圆弧我不知道。你最好问客服确认下,尤其是他们技术开发这卡的 人,我以前问过他们的人,有的告诉我有的卡S型曲线不太好呢。 还有点注意,就是相对坐标和绝对坐标问题了,两种计算方式不一样,我的经验是用相对坐标模式,调用运动控制 卡函数时是按照绝对坐标计算的思路,计算出相对的脉冲数,给函数提供参数的,这样电机运动更精准,函数模式 设置的是相对坐标模式。 到这我就帮不了你什么了,具体看你自己调试程序吧,我是做SMT行业的,没用到圆弧,就是T型S型曲线,直线 插补等等。没你们那么复杂。
takpod 2014-06-11
  • 打赏
  • 举报
回复
我最想清楚的是 是转进来的数据出错 还是 控制卡出错, 不过现在测试的结果好像是 控制卡出错,如果是真的就只能问客服怎么用 控制卡了,
takpod 2014-06-11
  • 打赏
  • 举报
回复
引用 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天,苦逼。

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

三,感谢,感谢,感谢!
baichi4141 2014-06-11
  • 打赏
  • 举报
回复
多线程不能同时修改一个数据或操作一个设备 起码四年前我用DMC5400的时候,它没有做线程安全,如果不在每一个d5400_XXX前后都加上线程锁,就会不知什么时候卡死
takpod 2014-06-10
  • 打赏
  • 举报
回复
引用 1 楼 piaobotudou 的回复:
1. 线程开始运行和结束的时间都不能预测 2. 保证在线程运行过程中使用的内存不能被其他地方销毁,如果使用公用变量应该注意同步 所以问题 1. 多次运行的时候,可能同时存在多个线程,会不会因为同步没有做好,或者其他地方删除了m_PtrArray中的内容,可是线程还可能在使用,可用CRITICAL_SECTION避免问题 2. 在线程里面delete需要保证这个指针只有这个线程在用 可以这样写 CPtrArray* pArrayForThread = new CPtrArray; //复制内容 //启动线程 线程用完了之后就可以delete。因为每次这个新内存都存在,并且线程不用了才会销毁 3. 在什么地方新建线程都可以,注意同步
1,我现在主要想知道这时 在线程里去读 Lpray 时面的数据会不会出错?(没有在别的地方修改m_PtrArray,也不在线程结束之前按下按键) 2,delete lpParameter的代码怎么写?我直接这样写会出错。
微型蚂蚁 2014-06-10
  • 打赏
  • 举报
回复
1. 线程开始运行和结束的时间都不能预测 2. 保证在线程运行过程中使用的内存不能被其他地方销毁,如果使用公用变量应该注意同步 所以问题 1. 多次运行的时候,可能同时存在多个线程,会不会因为同步没有做好,或者其他地方删除了m_PtrArray中的内容,可是线程还可能在使用,可用CRITICAL_SECTION避免问题 2. 在线程里面delete需要保证这个指针只有这个线程在用 可以这样写 CPtrArray* pArrayForThread = new CPtrArray; //复制内容 //启动线程 线程用完了之后就可以delete。因为每次这个新内存都存在,并且线程不用了才会销毁 3. 在什么地方新建线程都可以,注意同步

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧