Solved

C++-DLL and Delphi 3

Posted on 1998-11-09
9
494 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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
 
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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
  Included as part of the C++ Standard Template Library (STL) is a collection of generic containers. Each of these containers serves a different purpose and has different pros and cons. It is often difficult to decide which container to use and …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

792 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