why does this program have an exception in VC++ 2008 Express?

#include <conio.h>
//#include <C:\WString(v2.00).h>
#include <iostream>
#include <string>
using namespace std;

class WCS
{
public:
	wchar_t* string;
	WCS(const wstring& wstr)
	{
		wchar_t* c = new wchar_t [wstr.size() + 1];
		wcscpy(c,wstr.c_str());
		string = c;
	}
	~WCS()
	{
		delete [] string;
	}
	operator wchar_t*&()
	{
		return string;
	}
};

int main()
{
	wstring wstr(L"hello");
	wchar_t* const& c = WCS(wstr);
	wcout << c;
	_getch();
}

I tested it in a borland compiler & there was no exception. Perhaps there's a problem with VC++!

First-chance exception at 0x102670ef in Console.exe: 0xC0000005: Access violation reading location 0x00037000.
Unhandled exception at 0x102670ef in Console.exe: 0xC0000005: Access violation reading location 0x00037000.

I use VC++ 2008 Pro. It compiled, but it threw a warning about the use of wcscpy(). The error recommended the use of wcscpy_s() for security reasons.

cpp22210.cpp(14) : warning C4996: 'wcscpy': This function or variable may be unsafe. Consider using wcscpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Do you get something similar?

why does this program have an exception in VC++ 2008 Express?
I tested it in a borland compiler & there was no exception.

VC probably destructs the object as soon as the reference has been set i.e. before any output.

Just out of curiosity, when you run the program under borland, does the destructor get called before the "wcout << c"?

Do you get something similar?

yes, I used wcscpy_s & still I receive the same exception:

#include <conio.h>
//#include <C:\WString(v2.00).h>
#include <iostream>
#include <string>
using namespace std;

class WCS
{
public:
	wchar_t* string;
	WCS(const wstring& wstr)
	{
		wchar_t* c = new wchar_t [wstr.size() + 1];
		wcscpy_s(c,wstr.size(),wstr.c_str());
		string = c;
	}
	~WCS()
	{
		delete [] string;
	}
	operator wchar_t*&()
	{
		return string;
	}
};

int main()
{
	wstring wstr(L"hello");
	wchar_t* const& c = WCS(wstr);
	wcout << c;
	_getch();
}

I use Windows XP SP3.

VC probably destructs the object as soon as the reference has been set i.e. before any output.

no, see this

line 11: you should name that character array something else because string is declared in the header file <string>. Since you used using namespace std; there is now a name clash between std::string and the string you declared in your WCS class.

Your class would be a lot simpler if you would use std::wstring instead of wchar_t*. Afterall, that was the main objective of creating the std::string class in the first place -- to avoid all the problems with pointers.

no, see this

What's there is not quite same thing that you are doing in this thread (very close though).

However, you are not referencing the object that gets constructed, but rather its member variable. The object really gets destructed before the output.

So, to keep the object around long enough to see the output, it would be:

WCS const & ws = WCS(wstr);
wcout << ws.string;

And there is a little too-small-a-buffer hitch ...

wcscpy_s(c, wstr.size() + 1, wstr.c_str());

[EDIT]
A good string-catch by AD, so the above .string really should be something else that it is. But you get the point I think.

I commented out everything but the constructor/destructor and it still crashes. And changing string to just s didn't help either. Replaced wchar_t* with char*t and it works.

class WCS
{
public:
    wchar_t* s;

    WCS(const std::wstring& wstr)
	{
        s = new wchar_t[(wstr.size()+1) * sizeof(wchar_t)];
        wcscpy_s(s,wstr.size(), wstr.c_str() );
	}
	~WCS()
	{
		delete [] this->s;
	}
//	operator wchar_t*&()
//    {
//		return this->s;
//	}
};

int main()
{
    std::wstring wstr(L"Hello");
        
    WCS w(wstr);
    //wchar_t* const& c = w.operator wchar_t *&();
    //std::wcout << c;
    std::cin.get();
}

I did all you said. My final program, exception survived:

#include <conio.h>
#include <iostream>
#include <string>

class WCS
{
public:
	wchar_t* p;
	WCS(const std::wstring& wstr)
	{
		wchar_t* c = new wchar_t [wstr.size() + 1];
		wcscpy_s(c,wstr.size() + 1,wstr.c_str());
		p = c;
	}
	~WCS()
	{
		std::cout<< "destructed\n";
		delete [] p;
	}
	operator wchar_t*&()
	{
		return p;
	}
};

int main()
{
	std::wstring wstr(L"hello");
	wchar_t* const& c = WCS(wstr);
	std::wcout << c;
	_getch();
}

However, you are not referencing the object that gets constructed, but rather its member variable. The object really gets destructed before the output.

the exception occurs before destruction. I tested it. And another thing I should add to the "essential properties" is that a referece to a member is is enough to prevent destruction.

I reconstructed the project & even restarted my computer. the problem not solved yet.
Does this program have an exception in your computer?! (with VC ex)
if no, I'll have to reinstall VC!

Replaced wchar_t* with char*t and it works.

so you say there's problem with header files?

>>so you say there's problem with header files?
No. The program didn't like that constructor for some reason.

Success!

class WCS
{
public:
    WCS(const wstring& str)
    {
        s = new wchar_t[str.length()+1];
        wcscpy_s(s,str.length()+1, str.c_str());
    }
    ~WCS()
    {
        delete[] s;
    }
	operator wchar_t*&()
    {
		return this->s;
	}
protected:
    wchar_t* s;
};

int main()
{
    WCS m(L"Hello");
    const wchar_t* s = m.operator wchar_t *&();
    wcout << s << '\n';
    std::cin.get();
}

I did all you said.

I assume you are addressing me, and if so, the code is still somewhat 'off' with regard to what I meant

#include <conio.h>
#include <iostream>
#include <string>

class WCS
{
public:
	wchar_t* p;
	WCS(const std::wstring& wstr)
	{
		wchar_t* c = new wchar_t [wstr.size() + 1];
		wcscpy_s(c,wstr.size() + 1,wstr.c_str());
		p = c;
	}
	~WCS()
	{
		std::cout<< "destructed\n";
		delete [] p;
	}
	operator wchar_t*&()
	{
		return p;
	}
};

int main()
{
  std::wstring wstr(L"hello");
  //// not like this ...
  //// wchar_t* const& c = WCS(wstr);

  // construct the object and get a const reference to it 
  // to keep it around as long as needed here
  WCS const & obj_ref = WCS(wstr);
  std::wcout << obj_ref.p;

  _getch();
}

>> And another thing I should add to the "essential properties" is that a referece to a member is is enough to prevent destruction.
I think that it just does not apply here, you don't have a 'valid' object around in the first place (mm, interesting topic, maybe some draft-standard reading is in order).

>> Does this program have an exception in your computer?!
Yes, that's because the object is destroyed too soon.

No. The program didn't like that constructor for some reason.
Success!

Wow, this is getting actually quite entertaining :)

Sorry AD, but you made a radical change there. That is, now there is an object instantiated in the usual way, i.e. "WCS m(L"Hello");", i.e the code is pretty much guaranteed to work.

But the original problem arose due to the way the constructor was used and the attempt to reference the (more or less) temporary object.

[EDIT]
@CppBuilder
GCC docs state one aspect with regard to the temporary objects and their lifetime, I think it's quite relevant here, since you mentioned referencing member variables, so maybe check out Temporaries May Vanish Before You Expect.

Yes, that's because the object is destroyed too soon.

yes in Dev C++ & VC++ 2008, destructor is called before wcout. but in C++Builder it is called after wcout.
perhaps what VC does is the standard. but for sure what Borland compiler does is more justifiable!

And another thing I should add to the "essential properties" is that a referece to a member is is enough to prevent destruction.

I think I can add this forth essential property only for Borland compilers!
well, it's too bad:
in a Borland compiler WCS can be used as a function which returns a pointer to a memory that is deleted automatically at the end of block.
in VC++ we can't have such an automatically deleted poiter to heap memory!
can you solve the problem in VC++?!

I assume you are addressing me

I was addressing both you and Ancient Dragon. (why in English 'you' is overloaded but 'he' & 'his' are not ;)? sorry said that as an English learner :))

Thanks to all f trying to help me :)

in a Borland compiler WCS can be used as a function which returns a pointer to a memory that is deleted automatically at the end of block.

After reading that, it just occurred to me, that maybe you've been 'digging in too deep too long', so that you've actually forgotten that a regular stack-based object tends to do that thing, could it be?

so that you've actually forgotten that a regular stack-based object tends to do that thing, could it be?

no. stack-based object cannot be returned!
suppose wrote my own string class: MyString. now I want to use an API function which has a aparmeter with type "wchar_t*" :
void f(wchar_t* c);

now I can simply write f(WCS(mystr));
WCS(mystr) is destroyed automatically where not needed. WCS also doesn't reveal the main pointer of a string class.
there are some advantages if compilers allow! well my codes use hidden abilities of compilers to be automatic! I love complete automatic classes. they are like independant factories!
well this thread is done! :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.