Stats Cruncher
Stats Cruncher

Reputation: 153

What is wrong with strncpy_s() here?

I am reading a textbook and trying to solve the question given to readers.

The fallowing code is function definition from my source file of my answer.

I want to copy content of character strings to another ones.

I chose functions strncpy_s().

But it does not work.

Microsoft Visual Studio says Debug Assertion Failed!

I have no idea how to fix it.

cow.h

// class declarations

#include <iostream>
#ifndef COW_H_
#define COW_H_

class Cow {
char name[20];
char * hobby;
double weight;
public:
Cow();
Cow(const char * nm, const char * ho, double wt);
Cow(const Cow & c);
~Cow();
Cow & operator=(const Cow & c);
void ShowCow() const;  // display all cow data   
}; 
#endif

cow.cpp

// class methods

Cow::Cow(const char * nm, const char * ho, double wt)
{
    int len = std::strlen(nm);
    strncpy_s(name, len, nm, len);
    name[19] = '\0';

    len = std::strlen(ho);
    hobby = new char[len + 1];
    strncpy_s(hobby, len, ho, len);
    hobby[len] = '\0';

    weight = wt;
}

Cow::Cow()
{
    strncpy_s(name, 19, "no name", 19);
    name[19] = '\0';

    int len = std::strlen("no hobby");
    hobby = new char[len + 1];
    strncpy_s(hobby, len, "no hobby", len);
    hobby[len] = '\0';

    weight = 0.0;
}

Cow::Cow(const Cow & c)
{
    int len = std::strlen(c.name);
    strncpy_s(name, len, c.name, len);
    name[19] = '\0';

    len = std::strlen(c.hobby);
    hobby = new char[len + 1];
    strncpy_s(hobby, len, c.hobby, len);
    hobby[len] = '\0';

    weight = c.weight;
}

Cow::~Cow()
{
    delete [] hobby;
}

Cow & Cow::operator=(const Cow & c)
{
    if (this == &c)
        return * this;

    delete [] hobby;

    int len = std::strlen(c.name);
    strncpy_s(name, len, c.name, len);
    name[19] = '\0';

    len = std::strlen(c.hobby);
    hobby = new char[len + 1];
    strncpy_s(hobby, len, c.hobby, len);
    hobby[len] = '\0';

    weight = c.weight;
    return * this;
}

void Cow::ShowCow() const
{
    cout << name << ", " << hobby << ", " << weight << endl;  
}

usecow.cpp

  #include <iostream>
  #include "cow.h"


  int main()
  {
      Cow Japan;
      Japan.ShowCow();

      Cow America("Aspen", "Swim", 307.45);
      America.ShowCow();

      return 0;
  }

Upvotes: 2

Views: 15746

Answers (2)

Pete Becker
Pete Becker

Reputation: 76305

int len = std::strlen(nm);
strncpy_s(name, len, nm, len);

First, the second line should use len + 1 instead of len. And second, it should use strcpy instead of strncpy_s.

Calculating the length of the source (strlen(nm)) doesn't provide any information about the size of the target buffer (name). And since there is no information about the size of the target buffer, restricting the number of characters to copy is meaningless. So don't do all that wheel-spinning. Just copy the string:

strcpy(name, nm);

Upvotes: 1

Ari0nhh
Ari0nhh

Reputation: 5920

From strncpy_s documentation:

These functions try to copy the first D characters of strSource to strDest, where D is the lesser of count and the length of strSource. If those D characters will fit within strDest (whose size is given as numberOfElements) and still leave room for a null terminator, then those characters are copied and a terminating null is appended; otherwise, strDest[0] is set to the null character and the invalid parameter handler is invoked, as described in Parameter Validation.

Lets consider your code:

int len = std::strlen("no hobby");
hobby = new char[len + 1];
strncpy_s(hobby, len, "no hobby", len);

Second argument of strcpy_s is a size of buffer in characters. Fourth - number of characters copied. Since you are passing the same len variable, strcpy_s detects, that buffer has insufficient size (because there should be a space for the trailing \0) and invokes invalid parameters handler. This works correctly:

int len = std::strlen("no hobby");
hobby = new char[len + 1];
strncpy_s(hobby, len+1, "no hobby", len);

Check other places where you are using strncpy_s for this error. Also it is a good idea to actually read text in the debug assertion windows. In this case error source is pretty straightforward:

debug assertion failed

Upvotes: 6

Related Questions