1

I am running a short bit of code that will occasionally (very rarely) Access Violate on the Terminate/Free of my TThread. I am running many instances of these threads but this spot seems to be the only ones that is causing problems and it only does so once every 500 or so calls.

TThreadInheritor* Base= new TThreadInheritor(1);
  try {
    Base->Start();
    WaitForSingleObject((HANDLE)Base->Handle, 1000);
    MyBaseId = Base->scanvalue;
  }__finally {
    Base->Terminate();
    Base->Free();
  }

It is being thrown in my finally. My first guess was that WaitForSingleObject was timing out in a weird way and causing the Terminate and Free to mess up, but I'm not quite sure how that would happen. I didn't change anything to do with the Terminate/Free methods when I inherited from TThread.

Anyone know what could cause those two methods to access violate after so little code?

Ken White
  • 123,280
  • 14
  • 225
  • 444
user912447
  • 696
  • 1
  • 11
  • 31
  • 4
    Well, you could certainly start by at least _checking the return value_ of `WaitForSingleObject`... – ildjarn Oct 04 '11 at 23:54

2 Answers2

2

Never free a TThread that is still running. The base class TThread destructor is not safe in that regard. It does some pretty stupid things that can cause problems. ALWAYS make sure a TThread is fully terminated before freeing it. Use the WaitFor() method, or wait until WaitForSingleObject() reports WAIT_OBJECT_0.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

Firstly, do not use Base->Free(). Use delete Base; instead.

More importantly, you should call Base->WaitFor() after Terminate() to make sure it is actually terminated prior to deleting the object.

Base->Terminate();
Base->WaitFor();
delete Base;

Otherwise you'd be deleting the thread object (which your code / RTL may still be using) prematurely thus leading to the occasional access violation.

Or you could set the FreeOnTerminate property to true and forget about waiting / deleting the object altogether (be careful about running out of virtual memory though if you have too many threads since there's no 64-bit version of C++ Builder yet).

Zach Saw
  • 4,308
  • 3
  • 33
  • 49
  • Why should I not call base->Free()? If it an unsafe function I would imagine that it would not be included in the class. – user912447 Oct 05 '11 at 14:18
  • `TThread` derives from `TObject`, which is a Delphi class with a compatibility wrapper in C++. `Free()` is a method of `TObject`, which is why it exists in C++ at all, but it is only really used in Delphi. It should not be used in C++, always keep `new` and `delete` balanced in C++ instead. The compiler knows the class is based in Delphi and will make sure `delete` will destruct it correctly. – Remy Lebeau Oct 05 '11 at 15:43