?
Solved

Can you check this code for me?

Posted on 2002-06-05
29
Medium Priority
?
263 Views
Last Modified: 2007-12-19
Hi Experts,

I guess this is a very easy question for you...though not me :-(
I got Debug Assertion Failed error message in the following code:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

bool Find(istringstream is1);

int main()
{
     string myString="abc";
     istringstream is1(myString);
     cout<<Find(is1);
     return 1;
}

bool Find(istringstream is1)
{
     return true;
}

Can you tell me how to correct it?
And, can you tell me what is "using namespace std;" for?
0
Comment
Question by:learn
  • 11
  • 9
  • 7
  • +1
29 Comments
 
LVL 1

Accepted Solution

by:
Toad224 earned 240 total points
ID: 7058169
using namespace std; basically tells the compiler you're using the standard libraries, like <iostream>, and <string>  instead of like <iostream.h>.

I think you're problem is that is1 isn't passed as a reference parameter, you need to declare it as reference when you're using istringstream I believe.  Try this:

bool Find(istringstream & is1);

int main()
{
    string myString="abc";
    istringstream is1(myString);
    cout<<Find(is1);
    return 1;
}

bool Find(istringstream & is1)
{
    return true;
}

Hope this helps.  Good luck!
0
 

Author Comment

by:learn
ID: 7058180
Thanks a lot for your help.

But why we have to pass that by reference? I don't need to get the modified value of is1.
0
 
LVL 1

Expert Comment

by:Toad224
ID: 7058202
Well...  If you really don't want it to be modified, you can pass it as a const reference parameter by doing bool Find(const istringstream & is1);

It just needs to be passed as reference... like if you passed a istream file handle as a parameter, it would need to be passed as reference.

Good luck!
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:nietod
ID: 7058887
>> using namespace std; basically tells the compiler you're using
>> the standard libraries, like <iostream>, and <string>  instead
>> of like <iostream.h>.
That is a little missleading.

C++ supports namespaces which are scopes in which identifiers (names) of things (classes, constants, functions, etc) can be placed so they don't conflict with the same identifiers (same name) used in a different scope.

For example the STL uses the identifier "list" for one of its class templates.  There must be litteraly millions of other programs that use the word "list" for various other purposes.   Without namespaces, programmers would be unable to use the STL list, or would be forced to change the name of whatever it was they were calling "list" otherwise the compiler would find lots of errors.      But namespaces fix this.  an identifier used in one namespace does not conflict with the same identifier used in a different namespace.

All of the identifiers of STL are in the "std" namespace.  So none of the STL identifiers will conflict with any identifer in your program.  

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 7058894
If you need to refer to an identifier in a different namespace, you need to preceed its name with the namespace name and the scope resolution operator ("::").  For example

#include <string>
int string;

itn main()
{
   string = 0;   // Set the global integer called "string" to 0.
  std::string  AString;  // now declare an STL string.

   return 0;
};

note how "string" is used for two different purposes, but scope resolution is used to keep them clearly defined.

Note how the code above does not use "usign namespace std;"   That is a using definition.  When you place a using definition in a program it tells the program to place all the identifiers of the specified namesace (the std namespace int his example, but it can be any namespace, including ones you write) into the current namespace.  By doning this you no longer need to specify the namespace those identifiers come from.   i.e. it means you don't have to precceed everything with "std::".    

So basically it is a typing saver.    However the drawback to it is that it means that those names can now conflic witht he sames names used in your current namespace.   i.e. in your code you cannot use names that have been used byt he STL, like "string" or "vector".  otherwise you will get compiler errrors.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 7058899
Finally the STL header names do not end in .h.   Files like <iostream.h> are not officially part of the standard.  You should never use them.    Some compilers ship old versions of the STL with names like that.  Sometimes these old version do not use namespaces, thus if you use them you don't need to specify the "std" namesace.  however, they are unstandard files.  You have no idea what is in them.  They may be long out of date.  Stay away from them and use the standard files.

>> If you really don't want it to be modified, you can pass it
>> as a const reference parameter
>> by doing bool Find(const istringstream & is1);
That wonks only in the sense that it can be compiled.  You can't use the stream for much in that case.  For example you can't output to it.   (You can get the value it stores though.)

>> ike if you passed a istream file handle as a parameter,
>> it would need to be passed as reference.
No a file handle certainly can be passed by value and can be used for any operation when passed by value.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 7058916
>> you need to declare it as
>> reference when you're using istringstream I believe
By conventions streams are usually passed by reference--and often for good reason.   However, I can find no restriction that prevents passing them by value!

In fact, in my tests in VC I can pass them by value fine.


learn, what is the error you are getting?    

(Note, you probalby should be passing it by reference, not value, but I don't know that is the problem.)   Especially since you may find the behavior is not what you expect when you pass by value.  )
0
 

Author Comment

by:learn
ID: 7058985
To nietod,

Thank you for your comments!

The error was
Assertion Failed error
.....and something else.....
(in a black window)

This mornining, the same code causes different error:
Debug Error
...
DAMAGE: before Normal block
after I press the return button in the black window, it said:
User breakpoint from code at 0x4253f9

0
 
LVL 22

Expert Comment

by:nietod
ID: 7059143
I'm not getting those problems.  

The stream classes store pointers to stream buffer objects.   If you copy one of these streams, they will probalby end up sharing these pointers.  Then when the first stream object is destroyed, it deletes this stream buffer.  Then the next stream object either tries to use the stream buffer or it tries to delete it (not sure which) and you get a crash because the stream buffer was previously deleted.   Does that make sense?

Its the classic example of objects that store pointers needing copy constuctors to deal with copying or to prevent copyiung

However, the standard does not seem to deal with this issue.  I can't find any place where it tells how the copying is to be accomplished (which is not surprising at all)  So I expect to find something that says the copying is forbidden (by maing the copy constructor private and unimplimented)  But I can't find it.

I think I am missing something, because this woudl be too obvious a thing for them to simply miss.
0
 

Author Comment

by:learn
ID: 7059481
Hi nietod,

Did you say you copy-paste my code in your PC and run it without any problem!?
I am using VC++6.0 under Windows98
and the screen is DELL :-)
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059482
Very interesting.
There seems to be a problem with the VC++ copy constructor implementation.
I get a debug error on the following function:
void SomeFunct()
{
    const std::string myString="abc";
    std::istringstream is1(myString);
    std::istringstream is2 = is1;
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059484
here's the stack when the error occurs.

operator delete(void * 0x002f1138) line 47 + 81 bytes
std::allocator<char>::deallocate(void * 0x002f1138, unsigned int 3) line 64 + 38 bytes
std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >::_Tidy() line 181
std::basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >::~basic_stringbuf<char,std::char_traits<char>,std::allocator<char> >() line 32 + 74 bytes
std::basic_istringstream<char,std::char_traits<char>,std::allocator<char> >::~basic_istringstream<char,std::char_traits<char>,std::allocator<char> >() line 211 + 88 bytes
std::basic_istringstream<char,std::char_traits<char>,std::allocator<char> >::`vbase destructor'() + 40 bytes
SomeFunct() line 19 + 26 bytes
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059494
Coincidently, I have a feeling this error has something to do with reference counting.

For example if you run the following code, you don't get an error until after exiting the main:

const std::string myString="abc";
std::istringstream is1(myString);


void SomeFunct()
{
    std::istringstream is2 (is1);
}

     //Findxx(is1);
    //std::cout << Findxx(is1);
int main()
{
     SomeFunct();

     system("pause");
    return 1;
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059498
If you run this version of the program, then you get the error when trying to exit SomeFunct.

void SomeFunct()
{
     const std::string myString="abc";
     std::istringstream is1(myString);
    std::istringstream is2 (is1);
}

int main()
{
     SomeFunct();

     system("pause");
    return 1;
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059510
The above to examples leads me to believe that when is1 trys to destroy itself, is2 has already deleted it.

As a work around, you can use the str() member function, to force the impementation NOT to use referencing.
Example:
void SomeFunct()
{
const std::string myString="abc";
std::istringstream is1(myString);
std::istringstream is2 (is1.str());
}
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059523
Example using your code:

bool Find(istringstream is1x);

int main()
{
    string myString="abc";
    istringstream is1(myString);
    cout << Find((istringstream)is1.str()) << endl;
    return 1;
}

bool Find(istringstream is1x)
{
    return true;
}
0
 
LVL 22

Expert Comment

by:nietod
ID: 7059723
>> There seems to be a problem with the VC++
>> copy constructor implementation.
>> I get a debug error on the following function:
I don't get any error.  It works for me.

>> The above to examples leads me to believe that when
>> is1 trys to destroy itself, is2 has already deleted
I assume you mean the stream buffer objects?

What do you know about the rules governing the copying of stream objects?   I can find nothing.   I would think it should be forbidden.  
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059819
>>I would think it should be forbidden.  
I think you're right, but the only thing that I found was the following:

Section 27.4.4 of C++ Standard:
private:
basic_ios(const basic_ios& ); // not defined
basic_ios& operator=(const basic_ios&); // not defined

basic_istringstream derives from basic_ios via the following inheritance.

basic_istringstream->basic_istream->basic_ios
0
 
LVL 30

Expert Comment

by:Axter
ID: 7059823
learn,
If my interpretation of the standard is correct, you're using an undefined method.
I suggest you go with Toad224 recommendation, and pass by refference instead of by value.
0
 
LVL 22

Expert Comment

by:nietod
ID: 7059952
>>  think you're right, but the only thing that I found was the following:
That is what I was looking for.   I couldn't fiind it!   I'll have to look again.  (now that I have the secion number.)

>> f my interpretation of the standard is correct,
>> you're using an undefined method.
That's only the part of it.   The copy constructor is private and undefined.  This is done to make a class uncopyable.  (This is covered in the "Effective C++" series somewhere).  Any object of class with a private undefined copy constructor cannot be copied.  This means that objects of the class cannot be passed by value to a function--among other things.

If you attempt to perform a copy operation on a class like this you will get a compiler error.  That is the code will not compile.   but your code does compile.  (and it compiles form em too.)   This indicatest that the STL that comes with VC has a mistake.  They forgot to make the class's constructor private and unimplimented.  Because they forgot this, it allowed you to write code that the class can't handle (copied objects.)

Does that make sense?

>>  suggest you go with Toad224 recommendation, and
>> pass by refference instead of by value.
that was always a good recomendation, though it wasn't clear if that was the cause of the problem.  Now its prety clear that it is the cause of the problem, but partly the blame is with another programmer.  (P.J. Plauger, who wrote the VC STL.)
0
 
LVL 22

Expert Comment

by:nietod
ID: 7059957
Axter,
I still had the standard open to the very same section too.

I missed it because they have a section of the class labeled for constructors and the copy constructor isn't even mentioned there.   I shoudl have read more caefully.    Thanks.
0
 
LVL 30

Expert Comment

by:Axter
ID: 7060321
>>I still had the standard open to the very same section
>>too.

I don't even use my hard copy any more, because (IMHO) finding anything in the standard without the luxury of keyword search, is like finding a needle in a hey stack.
0
 

Author Comment

by:learn
ID: 7060401
Experts,

1. An expert in another Expert-site said I may find a VC++ bug. However, I think somebody before me must tried pass an istringstream by value....if it is a bug it should be a known bug.

2. How about Toad224's comment:
>like if you passed a istream file handle as a parameter,
it would need to be passed as reference.
That is another bug? Or, any 'stream' cannot be pass by value?

3. In fact, I have corrected my code to pass by reference, following Toad224's suggestion. But just not understand :-(
0
 
LVL 30

Expert Comment

by:Axter
ID: 7060415
According to the C++ standard, you're not allow to pass by value.
private:
basic_ios(const basic_ios& ); // not defined
basic_ios& operator=(const basic_ios&); // not defined

istream and istringstream both derive from basic_ios.  The standard defines basic_ios copy constructor and assignment operator as both private and not defined.

That means according to the standard, you can't pass istream or istringstream by value.
0
 
LVL 30

Expert Comment

by:Axter
ID: 7060418
>>That is another bug? Or, any 'stream' cannot be pass by
>>value?
The bug is that you're allow to compile the code in the first place.
According to the standard, you should NOT be able to compile code that passes istringstream by value.
0
 

Author Comment

by:learn
ID: 7060432
Hi Axter,

I would ask you a little more about this in a new quetion....
0
 
LVL 22

Expert Comment

by:nietod
ID: 7060444
>> 1. An expert in another Expert-site said I may find a VC++ bug.
Its a bug, but not in VC, its in the STL library that ships with VC.   (Which microsoft did not write.  This time its not their fault)

As Axter said, the library code should litteraly prevent your code from compiling.  The reason for this is that it is not practicle to write a stream class that can be copied (there are lots of reasons for this, but mostly because it makes managing the stream buffer objects a nightmare)   So the library is supposed to contain code that makes any attempt at copying a stream a compile time error-.  But the STL shipped with VC doesn't have this code, so the fact that the library allowed you to compile the code.  then the resulting program failed.

FYI You can do this type of thing in your own code.  If you give a class a private copy constructor, code outside of the class ((non-friend code) will not be able to copy objects of the class.   If you make the private copy constructor non-implimented (declare it, but don't give it a body (definition)) then no code (even the class iteself can copy the object.

 For example,

class NotCopyable
{
    int MemberInt;
public:
    NotCopyable(int i) : MemberInt(i) { };
private:
    NotCopyable(const NotCopyable &Src); // Private copy constructor.  Not implimented.
};


Then if you do.

  NotCopyable NC(5); // Okay.
  NotCopyable Copy(NC); // Error can't create a copy.
 
   *    *    *
   Function1(NotCopyable &NC); // Okay.
   Function2(NotCopyable NC) // Error, can't create a copy.
0
 

Author Comment

by:learn
ID: 7060493
To nietod,
Please accept my thanks and a little point in another posting...
0
 

Author Comment

by:learn
ID: 7060495
Thank you very much for the help!!
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

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…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

839 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