Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

strcpy_s in constructor

Status
Not open for further replies.

bkelly13

Programmer
Aug 31, 2006
98
US
Windows 7, Visual Studio 2008, C++

The question is: why is the strcpy_s returning an error that the destination is too small?

I am following a book and playing around with constructors. The constructor in question is this:
Code:
C_box( char * new_name, float w = 1.0, float l = 1.0, float h = 1.0 )
{
  if( new_name == NULL )
{
			name = NULL;
		}
		else
		{
			size_t name_size = strlen( new_name );
                   // this started with "name_size + 1" then bumped
                   // it up to 10.  That made no difference.
			name = new char[ name_size + 10 ];
			errno_t error_number = strcpy_s( name, name_size, new_name );
		}
		width = w;
		length = l;
		height = h;
	};

Two instances of the class are created:
Code:
	C_box box1;
	C_box box2( "two", 2.0, 2.0, 2.0 );

The first is okay (uses a different constructor), and the second fails at the strcpy_s. So I when step into the strcpy_s function the code shown is from file tcsscpy_s.inl and looks like:
Code:
_FUNC_PROLOGUE
errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC)
{
    _CHAR *p;
    size_t available;

    /* validation section */
    _VALIDATE_STRING(_DEST, _SIZE);
    _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);

    p = _DEST;
    available = _SIZE;
    while ((*p++ = *_SRC++) != 0 && --available > 0)
    {
    }
    if (available == 0)
    {
        _RESET_STRING(_DEST, _SIZE);
        _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE);
    }
    _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1);
    _RETURN_NO_ERROR;
}
Reference lines
_VALIDATE_STRING(_DEST, _SIZE);
_VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);

First I find it curious that the debugger does not provide any information about _DEST, _SIZE, etc, so I cannot determine what it is doing.
Regardless, the variable "available" gets the value 3, the size of the source string. The while loop does the copy and available bumps down to 0. That looks right to me. Then the debugger hits:
Code:
if (available == 0)
There is something wrong here.
The if is taken and and Visual Studio pops up an error box containaing, in part:
Expression:(L"Buffer is too small" && 0 )
What else could happen? Available starts at the size of the string being copied and counts down to zero. Why should this result in an error?

We need to know what a dragon is
before we study its anatomy.
(Bryan Kelly, 2010)
 
Add 1 to name_size in strcpy_s call: remember trailing zero byte in C text strings.
 
A better idea would be to stop messing with char* pointers in your C++ programs and use a [tt]std::string[/tt] in its place.

When you positively have no choice but to read it as a char array at some point, then use [tt]name.c_str()[/tt]




--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
ArkM,
I did not think of that. Thank you.

Not to take away from your post, But that led to some other tests. First, the help file for strcpy_s includes the line:
Code:
strcpy_s( string, "Hello world from " );
The help file appears to be wrong as the compiler says strcpy_s does not take 2 argugments.

Next the help file shows three more lines of code that contain strcat_s but not strcpy_s. This despite the fact that the top of the help page does not include strcat().

They also show the use of _countof as in:
Code:
 strcat_s( string, _countof(string), "strcat_s!" );

Maybe that returns the required value for strcpy(). However:
Code:
... char * new_name; ...
size_t name_size_b = _countof( new_name );
size_t name_size_b = _countof( *new_name );
Neither one of those two options will compile. Both of them solicit error C2784. I would paste the message in but the compiler has copy disabled for error messages. I guess they have decided that their error messages are proprietary.

So, does anyone know how to use _countof?
And, i presume I should just add one to the length when doing a strcpy_s. Is that correct?







We need to know what a dragon is
before we study its anatomy.
(Bryan Kelly, 2010)
 
Salem,

You are undoubtably right.
Problem is, I am not yet good at this and Horton's VS 2008 C++ uses char * all over the place. So I start with what he has. I presume that "char *" is an easy way to get pointers and illustrate the need for copy constructors.

I must wonder: Why did Horton, in his relatively recent book, use char * so much rather than std:string?

But that's really rhetorical, unless he lurks these pages we will never know his reasoning.

We need to know what a dragon is
before we study its anatomy.
(Bryan Kelly, 2010)
 
Better get *_s functions out of your head! IMHO these non-standard freaks add nothing to your program security and robustness.

Apropos, non-standard _countof macros works correctly for statically allocated arrays only. It's a simple "sizeof(a)/sizeof*a"...
 
It seems to me you need a different book.

That a "C++" book published a whole decade after the C++ standard was released is STILL using char* for strings is frankly a rip-off.

> I must wonder: Why did Horton, in his relatively recent book, use char * so much rather than std:string?
No doubt it is the same old book tarted up for the latest compiler, without actually revising any of the material.

Personally, I would go with this book list.

Accelerated C++ is well recommended, and it isn't some 1000+ page door stop.

I also suggest avoiding any book which mentions a particular vendor in the title. Even if the material is good, you're inevitably going to learn some things which are compiler specific. Whilst this is not a bad thing per se, you won't necessarily know it is compiler specific until you use another compiler. But by then, it's too late.

Product neutral books are more likely to focus on the language (which should be good for all compilers), rather than being tied to any particular compiler.




--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
Salem wrote:
Accelerated C++ is well recommended, and it isn't some 1000+ page door stop.I also suggest avoiding any book which mentions a particular vendor in the title. Even if the material is good, you're inevitably going to learn some things which are compiler specific. Whilst this is not a bad thing per se, you won't necessarily know it is compiler specific until you use another compiler. But by then, it's too late.

I am going with Accelerated C++.

On the vendor specific, Visual Studio C++ has an incredible number of utilities to display data within Windows and a myriad of ways to display that data. It seems like an incredibly difficult task to jump from just C++ to C++ for user interfaces in Windows. I have done a lot of coding, but not much C++ yet. I feel like getting fluent with Visual Studio is just as, if not more, difficult than learning the concepts of C++.

We need to know what a dragon is
before we study its anatomy.
(Bryan Kelly, 2010)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top