Solved

Implicit conversion problem

Posted on 1997-12-30
11
941 Views
Last Modified: 2012-08-13
I declare a function which takes a CString, and then pass a JString to it.  A typecast is necessary, so I create JString::operator CString () const, which builds and returns a CString that copies the JString.

Implicit conversion is done, and my function runs correctly, but on exiting, a memory library de-allocation error results.  If I _explicitly_ convert the JString parameter to a CString with a simple (CString) typecast, there's no problem!  Why does MSVC 1.52 produce different object code for these possibilities, and how can I fix the implicit conversion to work correctly?

(Or better still, is there a simple C++ string class available that is more efficient than the MFC CString class, and can return references to strings rather than creating gratuitous copies whenever you return string values, like Java's string class?)
0
Comment
Question by:Rumil
  • 5
  • 4
  • 2
11 Comments
 
LVL 5

Accepted Solution

by:
yonat earned 200 total points
Comment Utility
Why not use the standard string class (std::string)? It is a reference counted string, with many convinient operations. I don't know about VC 1.52, but VC5 has it (#include <string>). You can get free portable implementations from

http://www.metabyte.com/~fbp/stl/contrib/bstring.h
or (a differnt implementation)
http://www.metabyte.com/~fbp/stl/contrib/string.zip

Or you can use the rope class, developed by SGI. You can read about the differences between rope and string at
http://www.sgi.com/Technology/STL/string_discussion.html
http://www.sgi.com/Technology/STL/Rope.html
Using rope is especially important if your application is multi-threaded.

You can get rope with the rest of the STL portable version at
http://www.metabyte.com/~fbp/stl/
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I beleive that MFC's string class is well written and it works well with MFC.  (MFC procedures may take it as a parameters, so using a different type of string is inconvenient and may require lots of conversions, and since conversions are the problem...)

In any case, regardless of the string used, this problem should not happen.

The common problems I've seen in this area are: procedures that allocate memory that does not get disposed or procedures that return pointers to local variables or return structures that use pointers to local variables. Can you post the code of your conversion and any other necessary code?
0
 
LVL 5

Expert Comment

by:yonat
Comment Utility
The advantage of using the standard string class is that it is, well, standard. The advantage of using CString is that MFC uses it. So if you want your code to be portable, you should use the standard string. If your code is closely bound to MFC, use CString.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I was under the impression (maybe mistakenly as I re-read the question) that Rumil is using MFC, and thus felt that MFC's strings make sense.  In any case, the problem may not be in the string he chooses, but in the code that uses the string.
0
 

Author Comment

by:Rumil
Comment Utility
Problem: Where do I find good documentation for the standard string class?  It would take me a very long time to determine whether the class is adequate for my needs by reading the source code.  Even MFC is more legible.

MFC's CStrings are inadequate for my needs because it's not safe under Visual C++ 1.52 to return a reference to a CString.  Whenever I have a chain of functions that each pass a CString back to the last one, my program must return the CString "by value," wasting a lot of time copying memory.  Also, I've had some memory-allocation problems; code like <string = "Longer string", string = "Short"> will always leave the extra bytes allocated, and I know no way to free the space without deleting the whole string.

My code uses MFC, but not heavily enough to require frequent conversion if I thoroughly replace the CString class with JString in my own code.  However, I'm trying to replace CStrings with JStrings in just a few places at a time.  This strategy makes it easier to track down strange memory allocation errors like this one.


Here's the pertinent code:
void AFunction () {
  JString word = "Arbitrary";
  if (Find (word2) != NotFound)...
  }

int Find (CString s)    {  return Doc->Find (s);  }

int CMyDoc::Find (const CString& s) const
  {   ...  }

func CString JString::operator CString () const
  {
  CString retValue;
  for (int loop1 = 0;  loop1 < MSize;  loop1++)
    retValue += MData [loop1];
  return retValue;
  }


This code doesn't work.  But if I rewrite the first line as:
if (Find ((CString) word2) != NotFound)...
there are no problems!

I'm working around this specific problem simply by replacing the operator= with a ConvertToCString function, to force explicit conversion.  But I want to know what's going on to make sure I don't run into other, similar problems as I replace the CString class with my JString class.  Is it indeed just a bizarre Microsoft bug?
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 5

Expert Comment

by:yonat
Comment Utility
Hmm, doesn't sound like the standard string can solve your problems - your conversion operator is not being called implicitly. If this is a compiler bug, it is specific to 1.52 - I haven't seen it in 4.x and 5.0.

0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
I might see your problem, or just a typo.

the line

func CString JString::operator CString () const

should be just

JString::operator CString () const

you do not declare a return value ("CString") for a conversion operator and I have no idea what the "func" bit was.
0
 
LVL 5

Expert Comment

by:yonat
Comment Utility
nietod is right. You should reject my answer, and ask him to submit one.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
Does removing that stuff make the conversion work?
0
 

Author Comment

by:Rumil
Comment Utility
I've defined "func" to mean "inline" in my header files, and nothing at all in my source files, allowing me to conveniently move functions in and out of headers in a multi-module program as their complexity changes.  Nothing there.

Unfortunately, removing the "CString" return type didn't change anything either.  The problem is indeed compiler-related; MSVC produces different object code for the function-call depending on whether the typecast is done explicitly or implicitly.  (And yes, I tried deleting the conversion function long ago, just to make sure there were no other implicit conversions available.)

Under the assumption that this is just an obscure MSVC bug, I've replaced my operator CString function with a ConvertToCString function.  I've converted many instances of CStrings in my library to JStrings and CStringImages and haven't discovered any memory leaks yet.  I'm still nervous, though.
0
 
LVL 22

Expert Comment

by:nietod
Comment Utility
What is the difference in the code in the two cases?  That may reveal something.

Also I had missed one of your comments up there mentions a couple  of interesting things.  

You talk about returning strings as references to eliminate copying time.  As you might know, but in case you don't, that cannot be done unless the string is passed to the procedure in some way.  i.e. a conversion procedure cannot create a new (local) string and return a reference to it.  That will result in  problems.  The STL's string class, and I believe (or I would hope) the MFC string class uses reference counted string buffers.  This means that passing/returning strings by value does not involve copying the string and is very fast and efficient.  There is no need to pass/return strings by reference except where you actually need the reference.
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

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…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
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 be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

728 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

11 Experts available now in Live!

Get 1:1 Help Now