1. ホーム
  2. c++

[解決済み] ここでstrncpy_s()の何が問題なのでしょうか?

2022-01-30 12:55:36

質問

私は教科書を読んでいて、読者に与えられた問題を解こうとしているところです。

以下のコードは、私の解答のソースファイルからの関数定義です。

文字列の内容を別の文字列にコピーしたいのですが。

関数strncpy_s()を選びました。

しかし、うまくいきません。

Microsoft Visual Studio は、Debug Assertion Failed!

どうすれば直るのか見当もつきません。

cow.h

// クラス宣言

#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

// クラスメソッド

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;
  }

解決方法は?

から strncpy_s ドキュメンテーション :

これらの関数は、strSource の最初の D 文字を ここで,DはcountとstrSourceの長さの小さい方である。 このD文字がstrDest(そのサイズは numberOfElements)、ヌル終端記号のためのスペースがまだ残っている。 がコピーされ、末尾にNULLが付加される。 そうでない場合は、strDest[0]にヌル文字がセットされ、無効な パラメータ検証で説明したように、パラメータハンドラが起動されます。

あなたのコードを考えてみましょう。

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

の第2引数 strcpy_s はバッファのサイズ(文字数)です。4番目はコピーされた文字数です。を渡しているので、同じ len 変数を使用します。 strcpy_s は、バッファのサイズが不十分であることを検出し (末尾の \0 にスペースが必要なため)、無効なパラメータ・ハンドラを起動します。これは正しく動作します。

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

を使用している他の場所を確認します。 strncpy_s をクリックすると、このエラーが発生します。 また、デバッグのアサーション・ウィンドウで実際にテキストを読んでみるのも良いアイデアです。この場合、エラーソースは非常にわかりやすいものです。