Solved

C++-DLL and Delphi 3

Posted on 1998-11-09
9
491 Views
Last Modified: 2008-02-01
Hello,

I've written a DLL in Borland C++ 5.0.  One of the functions is a simple
concatenation function :

char* __stdcall _export StringTest(char* Str1, char* Str2)
{
   char* tmp;

   int l1 = strlen(Str1);
   int l2 = strlen(Str2);

   tmp = (char*) malloc(l1+l2+1);
   strcpy(tmp, Str1);
   strcat(tmp,Str2);
   return tmp;
}

This function works fine, but it has a memory leak : the memory
allocated for tmp is not released.

This function is called from a Delphi 3 application.  Can anyone tell me
how I can release the allocated memory, prefarably from the Delphi
application ?
I've tried freeing the memory just before the return instruction, but it
doesn't work.

Thanks in advance,

Johan

0
Comment
Question by:ppr
  • 3
  • 3
  • 2
  • +1
9 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 1177318
No way. You cannot release memory in a Delphi app that was allocated by a C++ DLL - they use different heaps for this. The only reliable way is to pass in a buffer allocated by the application, e.g.


char* export WINAPI StringTest(char* Str1, char* Str2, char *res)
{
   char* tmp
   strcpy(res, Str1);
   strcat(res,Str2);
   return res;
}

(NOTE the WINAPI modifier!)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1177319
Even if were possible (which it pretty much isn't ), these sort of designs where a procedure allocates memory for a return value and expects the caller to delete it, are notoriously dangerious.  You would ussually get a memory leak anyways because the calling code would probably forget to do the delete anyways, at least in some cases.
0
 

Author Comment

by:ppr
ID: 1177320
Thanks to AndersWP I was able to solve it the way I like it.  In the DLL, I use the GlobalAlloc API function and in the application I use the GlobalFree API.

But thank you for your reaction.

Johan
0
 
LVL 1

Accepted Solution

by:
TheGrinch earned 200 total points
ID: 1177321
I had a similar problem, and couldn't depend on the user of the function doing the "free" for me. So I did something like this...

char* export WINAPI StrTest(char* Str1, char* Str2, char *res)
{
  enum  { nstring = 100, stringl = 2000 };
  static  int  n = -1;
  static  char cbuf[nstring][stringl] = { '\0' };
          char *tmp = cbuf[n=(n+1)%nstring];

  strcpy(tmp, Str1);
  strcat(tmp, Str2);
  return tmp;
}

This function uses a set of 'nstring' "wraparound buffers" of length 'stringl' to hold the return values. After 'nstring' calls, it re-uses an old buffer.

This approach imposes two limitations: The maximum length of the result can't exceed 'stringl' and the maximum number of outstanding return values can't exceed 'nstring'. Depending on how your function is used, this might be a good solution.

You can change 'nstring' and 'stringl' to large values, but they are now on the stack. To make them VERY large, use...

  static char cbuf = (char*)calloc ( nstring, stringl );

After all, it's only virtual memory...

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 22

Expert Comment

by:nietod
ID: 1177322
>>Depending on how your function is used, this might be a
>> good solution.
This could never be a good solution.  For the few cases where you might be able to argure that it is safe, you could easily find better solutions.

If you need powerful string manipulation, use a string class.  It is far safer and far more powerful.

Besides, ppr already has a solution.  ready the question history.
0
 
LVL 1

Expert Comment

by:TheGrinch
ID: 1177323
nietod:

The approach I gave both solves the leakage problem, and allows clients of the DLL to continue to use the function WITHOUT BEING MODIFIED. That was the problem I had (an inability to modify the clients of the DLL).

Incidentally, I agree that there are limitations with my approach, which I clearly stated.

The approach chosen by ppr doesn't do this, nor does the use of a string class do this. Only my approach does this. But maybe this wasn't the problem. ppr wasn't clear whether the clients of the DLL could be changed. I assumed they couldn't. That is a fairly common problem when changing DLLs that are widely used.

I fully agree that a string class is the preferred approach, but your comment that "This could never be a good solution" is not only dead wrong, it reflects a "better than thou" attitude. I'm not taking any offense, but do suggest that you moderate your attitude just a bit :-)
0
 
LVL 1

Expert Comment

by:TheGrinch
ID: 1177324
nietod:

The approach I gave both solves the leakage problem, and allows clients of the DLL to continue to use the function WITHOUT BEING MODIFIED. That was the problem I had (an inability to modify the clients of the DLL).

Incidentally, I agree that there are limitations with my approach, which I clearly stated.

The approach chosen by ppr doesn't do this, nor does the use of a string class do this. Only my approach does this. But maybe this wasn't the problem. ppr wasn't clear whether the clients of the DLL could be changed. I assumed they couldn't. That is a fairly common problem when changing DLLs that are widely used.

I fully agree that a string class is the preferred approach, but your comment that "This could never be a good solution" is not only dead wrong, it reflects a "better than thou" attitude. I'm not taking any offense, but do suggest that you moderate your attitude just a bit :-)
0
 
LVL 22

Expert Comment

by:nietod
ID: 1177325
My thought was that you should never purposefuly write code like that.  If you are backed into it from another programmer's mistake then I guess I might be okay to. . . No it still wouldn't be okay, find the programmer, kill him, steel his code and fix it.  That would be acceptible  : - )
0
 

Author Comment

by:ppr
ID: 1177326
It's not exactly what I was looking for, but I think it will be usefull in the future.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now