-4

私は自分のコードに必要なものの骨子を与える模造文字列構造体を作成しようとしています (すべてが必要なわけではなく、コードをできるだけ高速で小さくしたいと考えています)。strcpyしたがって、 andのソースを取得する以外にstrcmp(それを許可されていますか?) struct hstring、コードを支援するために を作成しました。これまでのところ、次のものがありますstruct

struct hstring{
private:
    char *s; // pointer to what holds the string
    int size; // size of the string
public:
    hstring(){
        s=(char *)malloc(0);
        size=0;
    }
    void set(const char* str){ // set the string
        size=0;
        while(str[size]!='\0')
            size++;
        s=(char*)realloc((void *)s,size*sizeof(*s)); // reallocate memory to hold just enough for the character array
        for(int i=0;i<size;i++)
            s[i]=str[i];
        s[size]='\0';
    }
    bool is(const char* str){ // check if something is equal to the string
        int i=0;
        while((s[i]==str[i])&&(str[i]!='\0'))
            i++;
        if((i==size)&&(str[i]=='\0'))
            return true;
        return false;
    }
    inline char* get(){ // return the string
        return s;
    }
    inline int length(){ // return the size of the string
        return size;
    }
};

set()関数が機能する唯一の方法は、そこに明示的な文字列を配置するか、配列を持たない場合であることに気付きました。たとえば。

// This works
printf("\nTest1\n");
hstring test;
char tmp_c[50];
scanf("%s",tmp_c);
test.set(tmp_c);
printf("%s\n",test.get());

// This works
printf("\nTest2\n");
hstring test2[2];
test2[0].set("Hello ");
test2[1].set("world!");
printf("%s %s\n",test2[0].get(),test2[1].get());

// This works
printf("\nTest3\n");
hstring test3[2];
scanf("%s",tmp_c);
test3[0].set(tmp_c);
scanf("%s",tmp_c);
test3[1].set(tmp_c);
printf("%s %s\n",test3[0].get(),test3[1].get());

// This, what I want to do, does NOT work
printf("\nTest4\n");
hstring *test4 = (hstring *)malloc(2*sizeof(hstring));
for(int i=0;i<2;i++){
    scanf("%s",tmp_c);
    test4[i].set(tmp_c);
}
printf("%s %s",test4[0],test4[1]);
free(test4);

4 番目のテストが正しく実行されない理由がわかりません。コンパイルはできますが、test4 に到達して.set()関数内でメモリを再割り当てしようとするとクラッシュします。「アクセス違反の読み取り場所」エラーが表示され、想定されていない場所で書き込み/読み取りを行っていると思われました。ただし、正確な原因を特定することはできません (ただし、エラーの原因となっている行s=(char*)realloc((void *)s,size*sizeof(*s));は、文字配列のサイズを再割り当てしようとしたときであることがわかります。誰かが私が見落としていた問題に気づいていますか?

4

2 に答える 2

2

では、test4を使用malloc()して 2 つのオブジェクトにメモリを割り当てます。

hstring *test4 = (hstring *)malloc(2*sizeof(hstring));

ただし、コンストラクターはどちらに対しても呼び出されません。そのため、適切に初期化されていtest4[0]ません。test4[1]あなたのクラスメソッドはおそらく、参照されたオブジェクト初期化されていると想定しているため、非決定的な動作になります。

これを修正する方法は、を使用malloc()して を割り当てるのではなく、代わりにtest4使用することです。std::vector

std::vector<hstring> test4(2);

次に、オブジェクトがスコープ外になると適切に破棄されるためfree()、への呼び出しを削除できます。test4

クラス自体は、hstring割り当てられたメモリへのポインタを管理しています。そのため、そのメモリを解放するデストラクタを定義する必要があります。

struct hstring {
    //...
    ~hstring () { free(s); }
    //...
};

ただし、デストラクタが必要になったため、hstringクラスのコピー コンストラクタと代入演算子も定義する必要があります。これは3 つのルールとして知られています。

オブジェクトを使用してメモリを管理することで、この複雑さを回避できます。あなたのhstringクラスでは、代わりに内部char *を aにするのがおそらく最も簡単です。std::vector<char>その場合、デストラクタ、コピー コンストラクタ、および代入演算子は必要ありません。

于 2013-07-24T04:56:58.690 に答える
1

0 を渡すとmalloc、NULL を返すか、free を呼び出すために使用できる特別なポインタが返されます。単純に初期化するNULLか、'\0' 文字を含む空の文字列にすることをお勧めします。

printf("%s %s",test4[0],test4[1]);構造自体を印刷している印刷しています。あなたがすべき文字列を印刷するにはprintf("%s %s",test4[0].get (),test4[1].get ());

また、プログラムにメモリ リークがあります。構造体オブジェクトのポインターを編集mallocおよびrealloc編集しましたが、それらを解放しませんでした。shstring

malloc を実行するときにコンストラクターが呼び出されないことに気付きました。new/deleteの代わりにmalloc/を使用する必要がありますfree

必要な最小限の変更については、hstring *test4 = new hstring[2];割り当てdelete [] test4時と解放時です。

jxh の提案も参照してください。

于 2013-07-24T04:49:42.773 に答える