2

はじめに、私は Java プログラマーであり、C++ でのメモリ管理の問題にまだ慣れていないことに注意してください。

オブジェクトをASCII文字の文字列にエンコードするために使用される基本クラスがあります。基本的に、クラスはクラス メンバーを使用してさまざまなデータ型を 1 つの長い文字列に変換し、エンコードされたオブジェクト データを含む を呼び出し元にstringstream返します。char*

メモリ リークのテストでは、使用している実装ではメモリ リークが発生しやすいように見えます。これは、ユーザーがメソッドの戻り値を削除することを常に覚えておく必要があるためです。以下は、コードの関連部分の抜粋です。

    char* Msg::encode() 
    {
        // clear any data from the stringstream
        clear();
        if (!onEncode()) {
            return 0;
        }

        // need to convert stringstream to char*
        string encoded = data.str();
                    // need to copy the stringstream to a new char* because 
                    // stringstream.str() goes out of scope when method ends
        char* encoded_copy = copy(encoded);
        return encoded_copy;
    }

    bool Msg::onEncode(void)
    {
        encodeNameValue(TAG(MsgTags::TAG_USERID), companyName);
        encodeNameValue(TAG(MsgTags::TAG_DATE), date);
        return true;
    }

    bool EZXMsg::encodeNameValue(string& name, int value)
    {
        if(empty(value))
        {
            return true;
        }
                    // data is stringstream object
        data << name << TAG_VALUE_SEPARATOR << value << TAG_VALUE_PAIRS_DELIMITER;
        return true;
    }


    char* copy(string& source) {
        char *a=new char[source.length() +1];
        a[source.length()]=0;
        memcpy(a,source.c_str(),source.length());
        return a;
    }

アップデート

encode()まあ-結果がどのように消費されるかについて、もっと正確であるべきでした。これは boost:async_write に渡され、async_write が完了する前に文字列が範囲外になると思われるため、プログラムがクラッシュします。返された文字列を、メッセージを送信するクラスの存続期間中生きているクラス メンバーにコピーする必要があるようです (?)。

これは、encode()メソッドが実際に使用される方法です ( の戻り値を に変更した後string):

void iserver_client::send(ezx::iserver::EZXMsg& msg) {
       string encoded = msg.encode();   
       size_t bytes = encoded.length();
       boost::asio::async_write(socket_, boost::asio::buffer(encoded, bytes), boost::bind(&iserver_client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));    
}

これを行う適切な方法は、非同期書き込みする文字列のキュー/リスト/ベクトルを維持することです。ここに記載されているように(およびブーストの chat_client サンプルにも)。(しかし、それは別の問題です。)

4

4 に答える 4

1

特定の問題に対してa を使用しても適切に機能しますが、一般的な解決策は、生のポインターではなくstd::stringa を返すことです。std::unique_ptr

std::unique_ptr<char[]> Msg::encode() {
    :
    return std::unique_ptr<char[]>(encoded_copy);
}

ユーザーはそれunique_ptrを呼び出すと、新しいものを取得します。

auto encoded = msg.encode();
send(encoded.get());

encodedスコープ外に出て破棄されると、メモリは自動的に解放されます。

于 2013-07-14T23:02:28.720 に答える
1

を返すだけstd::stringです。とにかくそこに1つあります:

string Msg::encode() 
{
    // clear any data from the stringstream
    clear();
    if (!onEncode()) {
        return string{};
    }

    return data.str();
}

次に、呼び出し元は次のようになります。

Msg msg;
msg.userID = 1234;
send(msg.encode().c_str());
于 2013-07-14T02:56:12.927 に答える