BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: Access Violation in DLL

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (ActiveX)
View previous topic :: View next topic  
Author Message
Gord Cross
Guest





PostPosted: Mon Sep 27, 2004 8:53 pm    Post subject: Re: Access Violation in DLL Reply with quote



Hello,

I am trying to call a DLL (C++ Builder) from PB and I keep getting access
violations. The thing is, it will work for a few times then crap out. Does
anyone have any ideas? I think something is either locking or freeing
memory after the first time the DLL is called.

C++ Builder Code
~~~~~~~~~~~~~~

in header file ....

extern "C" __declspec(dllexport) bool __stdcall ShowEditor(char *);

in source file ...

bool __stdcall ShowEditor(char *ls_body)
{
int retCode = 0;
MainForm = new TMainForm(NULL);

//Create a memory stream to convert the string recieved from PowerBuilder
TMemoryStream *ms = new TMemoryStream();
ms->Write(ls_body,strlen(ls_body)+1);
ms->Position=0;

//Load the RTE
MainForm->RichEdit1->Lines->LoadFromStream(ms);

//Clear the Memory Stream to prepare for return trip
ms->Clear();

//Use editor
MainForm->ShowModal();

//Get All text from RTE
MainForm->RichEdit1->Lines->SaveToStream(ms);
ms->Position=0;

//Write Encoded text to string for PB
retCode = ms->Read(ls_body, ms->Size + 1);

delete MainForm;
delete ms;

return retCode;
}

Power Builder (the caller)
~~~~~~~~~~~~~~~~~~~

local external function declaration:

Public Function boolean ShowEditor(ref string lb_body) Library
"F:ProgrammingricheditDLLRichEditDLL.dll"

in onclick handler ...

string ls_body
boolean lb_retCode

//allocate space for the string
ls_body = space(10000)

lb_retCode = ShowEditor(ls_body)
if (lb_retCode) then
mle_1.text = ls_body
end if

//visual check to ensure we're within array bounds.
MessageBox("PB",string(rte_note))

Anyways, any comments would be greatly appreciated. I've aged over this ...

Gordon Cross
[email]gcross (AT) allnorth (DOT) com[/email]


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Mon Sep 27, 2004 9:59 pm    Post subject: Re: Access Violation in DLL Reply with quote




"Gord Cross" <g.cross (AT) allnorth (DOT) com> wrote


Quote:
ms->Write(ls_body,strlen(ls_body)+1);

You are not checking for ls_body to be NULL. If ls_body() is NULL, that
code will fail since strlen() will return 0 and you will be trying to access
more data then is actually available. In fact, you should get rid of the +1
altogether since the stream does not need to have the null terminator to
begin with.

Quote:
//Load the RTE
MainForm->RichEdit1->Lines->LoadFromStream(ms);

What is the value of the RichEdit's PlainText property? If it is set to
true, then you don't need the stream at all, you could assign ls_body to the
RichEdit directly:

MainForm->RichEdit1->Text = ls_body;

Quote:
//Write Encoded text to string for PB
retCode = ms->Read(ls_body, ms->Size + 1);

That is not a good way to handle things. For one thing, you are trying to
read more data then the stream actually has stored in it. Also, how are you
guaranteeing that the stored stream data won't exceed the size of ls_body's
allocated memory? I would strongly suggest that you add an additional
parameter to the function that specifies how large ls_body actually is, ie:

extern "C" __declspec(dllexport) bool __stdcall ShowEditor(char *, int);

#include <memory>
#include <algorithm>

bool __stdcall ShowEditor(char *ls_body, int max_body)
{
if( ls_body == NULL )
return false;

//Create a memory stream to convert the string recieved from
PowerBuilder
std::auto_ptr<TMemoryStream> ms(new TMemoryStream);
ms->Write(ls_body, strlen(ls_body));
ms->Position = 0;

//Load the RTE
std::auto_ptr<TMainForm> MainForm(new TMainForm(NULL));
MainForm->RichEdit1->Lines->LoadFromStream(ms.get());

//Clear the Memory Stream to prepare for return trip
ms->Clear();

//Use editor
MainForm->ShowModal();

//Get All text from RTE
MainForm->RichEdit1->Lines->SaveToStream(ms.get());
ms->Position = 0;

//Write Encoded text to string for PB
int retCode = ms->Read(ls_body, std::min(ms->Size, max_body));
if( retCode < max_body )
memset(&ls_body[retCode], 0, max_body-retCode);

return (retCode > 0);
}

Alternatively (depending on your needs):

extern "C" __declspec(dllexport) bool __stdcall ShowEditor(char *, int);

#include <memory>
#include <algorithm>
#include <stdio.h>

bool __stdcall ShowEditor(char *ls_body, int max_body)
{
if( ls_body == NULL )
return 0;

//Load the RTE
std::auto_ptr<TMainForm> MainForm(new TMainForm(NULL));
MainForm->RichEdit1->Text = ls_body;

//Use editor
MainForm->ShowModal();

//Write Encoded text to string for PB
int max = std::min(MainForm->RichEdit1->GetTextLen(), max_body);
return strncpy(ls_body, MainForm->RichEdit1->Text.c_str(), max);
}


Then you can call it like this (I don't know PB so this is a guess):

Public Function boolean ShowEditor(ref string lb_body, val int lb_max)
Library "F:ProgrammingricheditDLLRichEditDLL.dll"

lb_retCode = ShowEditor(ls_body, 10000)


Gambit



Back to top
Gord Cross
Guest





PostPosted: Tue Sep 28, 2004 4:43 pm    Post subject: Re: Access Violation in DLL (Case Solved ...) Reply with quote



Remy,

First a thanks for your help. I have been trying your suggestions. The
problems I was having were because I was whacking the null terminator for
the char * passed to the dll. I was overwriting it with my messy TMemory
stream calls (thanks).

Further, when writing the char * back I was using strncpy(char *dest, char
*src, MAX_LEN) - shame on me. If MAX_LEN is set to the actual max length of
the string - wups, there goes the NULL terminator for my char * again
leaving powerbuilder to float off into space when it tried to read the
string upon return (aka Access Violation). Should have been

strncpy(char *dest, char *src, MAX_LEN - 1);

And a final note. Something bizarre with the RichTextEdit->Text = "test";
it does not populate the control with the word 'test'. I've read about
problems with the Text property.

Anyways, Thanks for the help.



"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote

Quote:

"Gord Cross" <g.cross (AT) allnorth (DOT) com> wrote in message
news:41587de3$1 (AT) newsgroups (DOT) borland.com...

ms->Write(ls_body,strlen(ls_body)+1);

You are not checking for ls_body to be NULL. If ls_body() is NULL, that
code will fail since strlen() will return 0 and you will be trying to
access
more data then is actually available. In fact, you should get rid of the
+1
altogether since the stream does not need to have the null terminator to
begin with.

//Load the RTE
MainForm->RichEdit1->Lines->LoadFromStream(ms);

What is the value of the RichEdit's PlainText property? If it is set to
true, then you don't need the stream at all, you could assign ls_body to
the
RichEdit directly:

MainForm->RichEdit1->Text = ls_body;

//Write Encoded text to string for PB
retCode = ms->Read(ls_body, ms->Size + 1);

That is not a good way to handle things. For one thing, you are trying to
read more data then the stream actually has stored in it. Also, how are
you
guaranteeing that the stored stream data won't exceed the size of
ls_body's
allocated memory? I would strongly suggest that you add an additional
parameter to the function that specifies how large ls_body actually is,
ie:

extern "C" __declspec(dllexport) bool __stdcall ShowEditor(char *,
int);

#include <memory
#include
bool __stdcall ShowEditor(char *ls_body, int max_body)
{
if( ls_body == NULL )
return false;

//Create a memory stream to convert the string recieved from
PowerBuilder
std::auto_ptr ms->Write(ls_body, strlen(ls_body));
ms->Position = 0;

//Load the RTE
std::auto_ptr<TMainForm> MainForm(new TMainForm(NULL));
MainForm->RichEdit1->Lines->LoadFromStream(ms.get());

//Clear the Memory Stream to prepare for return trip
ms->Clear();

//Use editor
MainForm->ShowModal();

//Get All text from RTE
MainForm->RichEdit1->Lines->SaveToStream(ms.get());
ms->Position = 0;

//Write Encoded text to string for PB
int retCode = ms->Read(ls_body, std::min(ms->Size, max_body));
if( retCode < max_body )
memset(&ls_body[retCode], 0, max_body-retCode);

return (retCode > 0);
}

Alternatively (depending on your needs):

extern "C" __declspec(dllexport) bool __stdcall ShowEditor(char *,
int);

#include <memory
#include #include
bool __stdcall ShowEditor(char *ls_body, int max_body)
{
if( ls_body == NULL )
return 0;

//Load the RTE
std::auto_ptr MainForm->RichEdit1->Text = ls_body;

//Use editor
MainForm->ShowModal();

//Write Encoded text to string for PB
int max = std::min(MainForm->RichEdit1->GetTextLen(), max_body);
return strncpy(ls_body, MainForm->RichEdit1->Text.c_str(), max);
}


Then you can call it like this (I don't know PB so this is a guess):

Public Function boolean ShowEditor(ref string lb_body, val int lb_max)
Library "F:ProgrammingricheditDLLRichEditDLL.dll"

lb_retCode = ShowEditor(ls_body, 10000)


Gambit





Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (ActiveX) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.