c++での文字列クラスシミュレーションの実装とbasic_string::_M_construct null not validのエラーの原因について
cを学んだ後、c++を学び始めたところ、stringに出会い、その内部実装に興味を持った。cではchar型の配列で文字列を表現し、c++ではstringで文字列を表現する。cでは文字列は' \0' で終わっていると思い、stringオブジェクトに '\0' を初期化しようとしたがコンパイルは通ったが実行がうまくいかなかった。
そこで、'˶'がコンパイルされて通ったから、'A'のような一文字を代入してコンパイラがどうするか見てみようと邪推してみたら、コンパイラから'A ' is not a char* type does not matchと直接言われて唖然としてしまった
と疑問に思い、どうしたらいいのかわからず、上記のエラーをコピーしても納得のいく答えが見つからなかったので、文字列の実装をシミュレートしてみることにしました
そこで私は、この文字列の内部には動的に領域が確保されるはずだと考えました。
そこで、私はクラス
#include <iostream>
#include <cstring>
#include <cstdlib> //in order to use the exit function and the system function
using namespace std;
class HString
{
public:
HString();
HString(const char *);
/** print string */
int StrPrint();
/* Return the length of the string */
int GetLength()
{
return m_length;
}
/* ReSet */
int ReSet(const char *);
/* reload=assignment prevent memory leak */
const HString &operator=(const HString &);
/* Overload operator = to enable direct assignment with strings */
const HString &operator=(const char *r_str)
{
this->ReSet(r_str);
return *this;
}
virtual ~HString();
protected:
private:
char *m_str; //string dynamically allocated
int m_length; //the length of the string
int m_size; //size of current application space
void InitStr(const char *);//initialize the string
};
以下は、このクラスの実装です。
#include "HString.h"
HString::HString()
{
m_str = nullptr;
m_length = 0;
m_size = 0;
}
void HString::InitStr(const char *initStr)
{
if(nullptr == initStr)
{
cout << "HString::InitStr(const char *): initialization failed by " << __FILE__ << __LINE__ << endl;
exit(4);
}
int len = strlen(initStr);
m_length = 0;
m_size = 0;
m_str = new char[len + 1];
if(nullptr ! = m_str)
{
m_length = len;
m_size = len + 1;
memset(m_str, 0, m_size);
memcpy(m_str, initStr, m_size);
}
}
HString::HString(const char *initStr)
{
InitStr(initStr);
}
/** ReSet */
int HString::ReSet(const char *p_str)
{
if(nullptr == p_str)
{
cout << "HString::ReSet :The parameter is incorrect" << endl;
return 1;
}
int len = strlen(p_str);
if(len < 0)
{
cout << "HString::ReSet :get parameter is invailed" << endl;
return 2;
}
if(len < m_size - 1) //if the allocated string is less than the current allocated space length, assign it directly
{
memset(m_str, 0, m_size);
memcpy(m_str, p_str, len + 1);
m_length = len;
}
else // otherwise space reallocation
{
if(nullptr == m_str) //if object string has no space
{
InitStr(p_str); //initialize
}
else
{
char *p_temp = new char[len + 1];
if(nullptr == p_temp)
{
cout << "relloc failed!" << endl;
return 3;
}
else
{
memset(p_temp, 0, m_size);
delete m_str;
m_str = p_temp;
p_temp = nullptr;
m_size = len + 1;
m_length = len;
memcpy(m_str, p_str, m_size);
}
}
}
return 0;
}
/* Overload=assignment Prevent memory leaks */
const HString & HString::operator=(const HString &other)
{
if(this ! = &other) //if passed in other than itself
{
if(other.m_size <= this->m_size)
{
memset(this->m_str, 0, this->m_size);
memcpy(this->m_str, other.m_str, other.m_size);
this->m_length = other.m_length;
}
else
{
if(nullptr ! = this->m_str)
{
delete this->m_str;
}
this->m_str = new char[other.m_size];
memcpy(this->m_str, other.m_str, other.m_size);
this->m_length = other.m_length;
this->m_size = other.m_size;
}
}
return *this;
}
int HString::StrPrint()
{
if(0 == m_length || nullptr == m_str)
{
cout << "NULL" << endl;
return 1;
}
cout << m_str << endl;
return 0;
}
HString::~HString()
{
if(nullptr ! = m_str)
{
delete m_str;
m_str = nullptr;
}
}
私の能力の最大限に文字列をシミュレートする過程で、私は、再割り当てを達成するために、そう、メモリリークと空間の正当な使用しないために、我々は現在のアプリケーション空間のサイズを記録する必要があります文字列の長さの量は、関数strlenを使用する、私はプログラムのデバッグで見つかったstrlenで死亡した問題を発見しました。
そこで、もしポインタが' \0' を指しているならば、そのアドレスは何だろうと考えました。初期オブジェクトで渡したのは char 型のポインタなので、'A' など一文字を渡すと、コンパイラは直接エラーを報告します。型はそうではありませんが '\0' を渡すのは問題ないです。
だから
ようやく原因がわかりました。
strlenにNULLポインタを渡すと、NULLが指す空間にはアクセスできないのでプログラムが死んでしまうので、私のInitStrメソッドは引数を判断していないことに気づき、すぐに上記のコードのように修正しました。
そして、書いたクラスのオブジェクトを'˶'ᴗ'˶に代入した後
次に
コード内に発見
14行目でポップアップ表示されます
その後、私はそれを得た
std::logic_error' のインスタンスをスローした後に呼び出される終了処理
what(): basic_string::_M_construct null not valid
エラーの意味
おめでとうございます~!私の問題はまさにこれで解決です。
このクラスは、ヒープ領域でスペースを適用するときに文字列とは異なるはずですので、したがって、いくつかの効率の問題があるかもしれませんが、私はちょうどエラーを探索したいので、いくつかの機能が実装されていない、軽く兄を噴霧してくださいヾ(≧▽≦)ノ
)o
*
printf("233を見てくれてありがとう!")。
関連
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++
-
[解決済み】バイナリサーチツリーのデストラクタ
-
[解決済み】C++ - ネストされたインクルード - 「インクルードが深すぎてエラーになる」ことの回避
-
[解決済み] 文字列定数の前にunqualified-idを指定する必要があります。
-
[解決済み] コンパイラー "error: 'const something' を 'this' 引数に渡すと修飾子が破棄される"
-
[解決済み] エラー C2100 - 不正な方向性
-
[解決済み] プリプロセッサディレクティブに続く予期しないトークン - 改行が期待される
-
[解決済み] Cin.Ignore()が動作しない
-
[解決済み] コンテナクラス シーケンス c++
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] 非標準の構文。メンバへのポインタを作成するには '&' を使用します。
-
[解決済み] xutility.h エラー C2064: 項目が引数を 2 つ取る関数として評価されない
-
[解決済み] Mingw libgcc_s_sjlj-1.dll is missing
-
[解決済み] 未割り当てのメモリが0xCCと表示されるのはなぜですか?重複
-
[解決済み] リンクリストのコピーコンストラクタの作成
-
[解決済み] SFML の描画プリミティブを VertexArray から取得する。
-
[解決済み] CMAKE_C_FLAGSに付加する。
-
[解決済み] 1つの.cppファイルに複数のクラスを定義することは可能ですか?
-
[解決済み] 式はクラス型を持つ必要があります。- クラスオブジェクトのベクトル