Home
Reply
Regular Visitor
sunfish
Posts: 3

api_change_body_trans() bring on memory leak in Thread-Safe ACIS

 

Hello everybody!

 

    I create tow body(pBlock1 and m_pBlock), call the function api_change_body_trans  for  a pBlock1 and delete the pBlock1 in the construction function of the test_thread_work class,  and then i use plane slice the m_pBlock and delete the slice-wirebody in the thread function, and, delete the m_pBlock in the destruction function of the test_thread_work class,  lastly, exit process. i found the memory leak log in output;  but when i comment api_change_body_trans code, and restart the application, i found no leaks in log.  why?

 

the detailed test code as below:

.......

.......
 thread_work_base::initialize(1, start_acis, stop_acis);

 test_thread_work  testwork;

........

........

 

  

class test_thread_work : public thread_work_base
{
public:

   test_thread_work()
   : m_pBlock(NULL)
  {

     SPAposition pt1(-100, -100,-100); 
     SPAposition pt2(100, 100, 100); 

 

     BODY* pBlock1(NULL);

     api_solid_block(pt1, pt2, pBlock1);

     api_solid_block(pt1, pt2, m_pBlock);

     api_change_body_trans(sp, NULL);

     api_del_entity(pBlock1);
   }

protected:
 virtual  void process( void* arg)

  {

     if (m_pBlock != NULL)
     {
        CRITICAL_BLOCK(m_mutex)
        SPAposition pt(0, 0, 0);
        BODY*slice(NULL);
        SPAunit_vector normal(0, 0, 1);
        api_planar_slice(m_pBlock, pt, normal, slice);
        api_del_entity(slice);
     }

  }

 

  void run()
  {
       thread_work_base::run((void*) 0);

       thread_work_base::sync();
  }


public:
   ~test_thread_work()
   {

      if (m_pBlock != NULL)
      {
         api_del_entity(m_pBlock);
         m_pBlock = NULL;
      }
   }

 

private:
 BODY* m_pBlock;
};

 

 

It would be nice if somebody could give me some advice for that problem.

Spatial Employee
Kevin
Posts: 9

Re: api_change_body_trans() bring on memory leak in Thread-Safe ACIS

I have to admit, I'm confused with this example - so I'm just going to talk about some things I see.

 

 

 

First, your implementation of test_thread_work.  The constructor will be called by the main thread which creates m_pBlock, but you proceed to slice m_pBlock on the worker thread.  This will immediately result in a "mixed streams" exception, as it should.  A BODY created by one thread on it's history stream cannot be modified by another thread.  To move a BODY between threads, we recommend using api_deep_copy.  Note however, that the act of deep-copying, while fast, isn't zero cost - keep this is mind as you design.  When I think about workflows using threads and ACIS, I always aim for a design that pushes as much of the BODY creation/deletion to the worker threads, minimizing (or eliminating) the need to move ENTITYs between threads.

 

 

 

Next, it isn't clear what sp is when you call api_change_body_trans( sp, NULL ).  And your run method is protected, so there is no way to call it from main (which your example doesn't show but I assume is your goal). 

 

 

 

Next, after fixing the compile errors, I don't see any leaks from your program.  It runs clean and without leaks.  Can you specify what leaks you're seeing in your leak report?

 

 

 

Finally, I rewrote your example to do *something* on the worker thread.  It may not be what you're looking for, but it works.

 

................

................

 

test_thread_work testwork;

testwork.run(0);

testwork.sync();

................

...............

  

 

class test_thread_work : public thread_work_base
{
public:

 test_thread_work()
  : m_pBlock(NULL)
 {
 }

protected:
 virtual void process( void* arg)
 {
  BODY *pBlock1=NULL;
  SPAposition pt1(-100, -100,-100);
  SPAposition pt2(100, 100, 100);
  api_solid_block(pt1, pt2, pBlock1);
  api_change_body_trans(pBlock1, NULL);

  SPAposition pt(0, 0, 0);
  BODY*slice(NULL);
  SPAunit_vector normal(0, 0, 1);
  api_planar_slice(pBlock1, pt, normal, slice);
  api_del_entity(slice);
  api_del_entity(pBlock1);
 }

public:
 ~test_thread_work()
 {
  if (m_pBlock != NULL)
  {
   api_del_entity(m_pBlock);
   m_pBlock = NULL;
  }
 }

private:
 BODY* m_pBlock;
};

Regular Visitor
sunfish
Posts: 3

Re: api_change_body_trans() bring on memory leak in Thread-Safe ACIS

Hi Kevin,

 

      Thrank you so much for your help, and sorry for my poor description.

when i use the Thread-Safe ACIS to develope our aplication,  i found memory leak, the problem puzzled me, so i use the last test example for search the real reason of the memory leak, but i have not reproducted it in the test program. however, i found the other leak which in test program. please see the attachment.

 

the original code,

void CTestDlgDlg::OnBnClickedButton1()
{
	SPAposition pt1(-100, -100,-100);  
	SPAposition pt2(100, 100, 100);  
	BODY* block(NULL);
	api_solid_block(pt1, pt2, block);

	SPAtransf Rotatetransf = rotate_transf(asin(-1.0), SPAvector(0, 0, 1));
	api_apply_transf(block, Rotatetransf);
	api_change_body_trans(block, NULL);

	ENTITY* Cp(NULL);
	api_deep_down_copy_entity(block, Cp);

	BODY* sph(NULL);
	api_make_sphere(150, sph);

	{
		test_thread_work worker((BODY*)Cp);
		worker.DoProcessWithThreads();
	}

	api_del_entity(block);
	api_del_entity(Cp);
	api_del_entity(sph);
}

 

if i change code as below, that will solve this leak problem.

void CTestDlgDlg::OnBnClickedButton1()
{
 SPAposition pt1(-100, -100,-100); 
 SPAposition pt2(100, 100, 100); 
 BODY* block(NULL);
 api_solid_block(pt1, pt2, block);

 SPAtransf Rotatetransf = rotate_transf(asin(-1.0), SPAvector(0, 0, 1));
 api_apply_transf(block, Rotatetransf);
 api_change_body_trans(block, NULL);

 ENTITY* Cp(NULL);
 api_deep_down_copy_entity(block, Cp);

 BODY* sph(NULL);
 api_make_sphere(150, sph);

 //{
  test_thread_work worker((BODY*)Cp);
  worker.DoProcessWithThreads();
 //}

 api_del_entity(block);
 api_del_entity(Cp);
 api_del_entity(sph);
}

  or

 

void CTestDlgDlg::OnBnClickedButton1()
{
	SPAposition pt1(-100, -100,-100);  
	SPAposition pt2(100, 100, 100);  
	BODY* block(NULL);
	api_solid_block(pt1, pt2, block);

	SPAtransf Rotatetransf = rotate_transf(asin(-1.0), SPAvector(0, 0, 1));
	api_apply_transf(block, Rotatetransf);
	api_change_body_trans(block, NULL);

	ENTITY* Cp(NULL);
	api_deep_down_copy_entity(block, Cp);

	//BODY* sph(NULL);
	//api_make_sphere(150, sph);

	{
		test_thread_work worker((BODY*)Cp);
		worker.DoProcessWithThreads();
	}

	api_del_entity(block);
	api_del_entity(Cp);
	//api_del_entity(sph);
}

 but i don't understand the profound reason.