I am just posting in the hopes that somenone can explain a problem I seem to be having with Turbo C++. My application basically has two forms (Form1 and Form2). Form1 is the main form and Form2 is created dynamically, as the result of a button click event, from Form1 with the following code:

TForm2 *Form2 = new TForm2(this);
Form2–>ShowModal();

Form2 is not included in the Auto_Create forms list under Project Options. Form2 accesses a thread object, derived from the TThread class, called Thread. A new instance of the thread is created with the following code:

Thread *Thread1 = new Thread(true);

This is set running following a button click event with the following code:

Thread1->Resume();

The thread updates the contents of a TMemo object named Memo1 located on Form2. The thread code looks somthing like this:

void __fastcall Thread::Execute()
{
Synchronize(&UpdateMemo)
}
//---------------------------------------------------------------------------
void __fastcall Thread::UpdateMemo(void);
{
Form2->Memo1->Lines->Add("Thread Running!");
}
//---------------------------------------------------------------------------

The UpdateMemo function is defined in the Thread header file as:

void __fastcall Thread::UpdateMemo(void);

For some reason this code generates an access violation and I can't figure out why. If I include Form2 in the Auto_Create forms list under Project Options the thread runs (without generating errors), but doesn't update Memo1!! If I compile Form2 on its own or include Form2 in the Auto_Create forms list under Project Options and display it using the code:

Form2–>ShowModal();

without creating it dynamically, the thread runs and updates Memo1 as it should. I am guessing therefore that the problem arises from the way that Form2 has been created. Any help would be much appreciated as I am really quite stumped!

Many thanks in advance.

Ben.

Recommended Answers

All 8 Replies

Interesting. :)
Do you have global and/or static variables anywhere ?
Also can you post:
- TForm2.h
- TForm2::TForm2() implementation

Interesting. :)
Do you have global and/or static variables anywhere ?
Also can you post:
- TForm2.h
- TForm2::TForm2() implementation

Here is the code from all three Units. This is not the actual project I am working on but the following code replicates the problem:

Unit1.h (Form1):

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE-managed Components
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

Unit1.cpp (Form1):

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TForm2 *Form2 = new TForm2(this);
Form2->ShowModal();
}
//---------------------------------------------------------------------------

Unit2.h (Form2):

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published:	// IDE-managed Components
	TButton *Button1;
	TMemo *Memo1;
	void __fastcall Button1Click(TObject *Sender);
private:	// User declarations
public:		// User declarations
	__fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif

Unit2.cpp (Form2):

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;

Thread *Thread1 = new Thread(true);
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Thread1->Resume();
}
//---------------------------------------------------------------------------

Unit3.h (Thread):

//---------------------------------------------------------------------------

#ifndef Unit3H
#define Unit3H
//---------------------------------------------------------------------------
#include <Classes.hpp>
//---------------------------------------------------------------------------
class Thread : public TThread
{
private:
protected:
	void __fastcall Execute();
public:
	__fastcall Thread(bool CreateSuspended);
	void __fastcall Thread::UpdateMemo(void);
};
//---------------------------------------------------------------------------
#endif

Unit3.cpp (Thread):

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit3.h"
#include "Unit2.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall Thread::Thread(bool CreateSuspended)
	: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall Thread::Execute()
{
for (int i = 0; i <= 1000; i++)
{
Synchronize(&UpdateMemo);
}
}
//---------------------------------------------------------------------------
void __fastcall Thread::UpdateMemo(void)
{
Form2->Memo1->Lines->Add("Thread Running");
}
//---------------------------------------------------------------------------

Thanks,

Ben.

Couldn't figure anything from the code, given that it's not complete.
- How does Thread get Form2 obj?
- The access violation could be because one of the variables (Form2 or Memo1 or Lines) is uninitialized.
But can't figure out any of these from the code.
Just a couplea other thoughts:
- Check the owner's value when TForm2::TForm2(TComponent* Owner) gets called. Print out some instance specific info of TComponent that's passed. May it's different when "framework" creates it (instead of when you create it viz Form1 object)
- Other thing that I suspect more is, Memo, is an "// IDE-managed Components", so perhaps when IDE creates the Form2 (via your project settings) it takes care of init'ing it somehow?

Many thanks for your reply. I am afraid I am a reasonably new to C++ so you will have to excuse my ignorance.

I believe thread can locate the Form2 object by means of the include statement at the top of Unit3.cpp...

#include "Unit2.h"

As to the initialisation state of Form2 and Memo I am not sure how I would go about checking this. Any direction would be much appreciated. I assumed that as objects are created on the form at design time, they would initialised in exactly the same way irrespective of whether the form they are associated with is dynamically created or automatically created when the program runs. Is this not the case?

How would I go about checking the initialisation state of Form2 and Memo1 etc so I can determine whether any difference arises as the result of the different ways of creating the form? Any further help would be much appreciated.

Many thanks,

Ben.

BTW: Although the code posted is not from the project I am working on, it is complete and should compile and replicate the problem I am experiencing.

I think I've cracked it!! If I create Form2 using the following code

Form2 = new TForm2(this);
Form2->ShowModal();

Instead of

TForm2 *Form2 = new TForm2(this);
Form2->ShowModal();

the thread is now able to access the TMemo component on Form2. I'm not entirely sure why this works so if anyone has a couple of minutes spare and can offer me an explaination it would be much appreciated.

Thanks for taking the time to look at my code and offering some thoughts thekashyap . Cheers,

Ben.

// Your thread accesses the form via a variable named 'Form2'
// The 'Form2' variable below is local to the function and hence 
// hides the intended 'Form2' variable i.e. the correct 'Form2' does 
// not get assigned to anything.
TForm2 *Form2 = new TForm2(this);  
Form2->ShowModal();

He he.. :)
Stupid bug..
mitmkar has already explained it. Check out http://www.functionx.com/cppcli/variables/Lesson22.htm if still not clear.
PS: To catch such bugs in future, check the compiler option to increase the warning level. In Sun workshop it was +w2. RTM.
Better way is to use lint (http://www.splint.org/win32.html) though.

Totally unrelated to the problem cheat sheet for Turbo C++ found while looking for compiler guide.. http://www.sff.net/people/brian-larson/lab%20turbo%20c.htm

As to the initialisation state of Form2 and Memo I am not sure how I would go about checking this. I assumed that as objects are created on the form at design time, they would initialised in exactly the same way irrespective of whether the form they are associated with is dynamically created or automatically created when the program runs. Is this not the case?

How would I go about checking the initialisation state of Form2 and Memo1 etc so I can determine whether any difference arises as the result of the different ways of creating the form? Any further help would be much appreciated.

Couldn't help commenting: So a good practice is to initialize all your pointers to NULL (or 0) in c'tor (OR assign a valid address).
Also set it back to NULL once the object to which points to is deleted. Usually d'tor.
If you always ensure that you do this, you can always check anywhere in the code: if your pointer is NULL then it's not initialized correctly, else it's usable.

If you don't initialize it the problem is it'll contain junk value and if you're really unlucky it might even work ! :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.