2013-10-14 14 views
8

私はValgrindを使用して自分のコードでメモリリークを探しましたが、メモリリークは検出されませんでした。単一の関数/クラスメソッド:"初期化されていないバイトを指している" Valgrindのエラー

==17043== ERROR SUMMARY: 10100 errors from 3 contexts (suppressed: 0 from 0) 
==17043== 
==17043== 100 errors in context 1 of 3: 
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s) 
==17043== at 0x5441DA2: send (send.c:28) 
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x404F1C: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== Address 0x7feffff61 is on thread 1's stack 
==17043== Uninitialised value was created by a stack allocation 
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== 
==17043== 
==17043== 100 errors in context 2 of 3: 
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s) 
==17043== at 0x5441DA2: send (send.c:28) 
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x404E8A: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== Address 0x7feffff61 is on thread 1's stack 
==17043== Uninitialised value was created by a stack allocation 
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== 
==17043== 
==17043== 9900 errors in context 3 of 3: 
==17043== Syscall param socketcall.sendto(msg) points to uninitialised byte(s) 
==17043== at 0x5441DA2: send (send.c:28) 
==17043== by 0x404C2D: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x404EE8: unix_socket::sendVectorXd(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== by 0x401F2A: main (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== Address 0x7feffff61 is on thread 1's stack 
==17043== Uninitialised value was created by a stack allocation 
==17043== at 0x404BE6: unix_socket::sendMsg(char, double) (in /home/joao/CloudPT/Bolsa/Webots/controllers/darwin-pi2/client) 
==17043== 
==17043== ERROR SUMMARY: 10100 errors from 3 contexts (suppressed: 0 from 0) 

sendMsg(const char _type, const double _value)、エラーがで指していることを、unix_socketクラスの一部です:

//... 
typedef struct{ 
    char type;  
    double value; 
} MESSAGE; 

//... 
int unix_socket::sendMsg(const char _type, const double _value){ 
    MESSAGE msg; 
    msg.type=_type; 
    msg.value=_value; 
    int n = send(client_sock, &msg, sizeof(msg), 0); 
    if (n < 0) { 
     perror("send"); 
     return -1; 
    } 
    c_sent=msg.type; 
    v_sent=msg.value; 
    return 0; 
} 

私は問題が何であるかが表示されません。初期化されていない値はどこですか?または、私はValgrindによって報告されたエラーを無視する必要がありますか? MESSAGE構造体で

答えて

13

ルック:によるデータ構造配向へ

typedef struct{ 
    char type;  
    double value; 
} MESSAGE; 

valueのアドレスは、ワードサイズの倍数のアドレスに位置合わせするように強制されてもよいです。したがって、いくつかの未使用バイトはMESSAGE::typeと​​の間に埋め込まれます。これらは初期化されていないバイトでValgrindによって報告されています。

回避策として、構造体全体を強制的にmemset()で初期化することができます。

MESSAGE msg; 
memset(&msg, 0, sizeof(MESSAGE)); 
msg.type=_type; 
msg.value=_value; 
+1

代わりに、構造体をバイトベクトルにパックして送信し、各要素の正確なサイズに引き締めてください。ワイヤを介して構造体を送信することは決して偉大な考えではありません。現在のメカニズムを読んでいるクライアントは、構造体のパディングが何であるかを知る方法がないため、結果として、値が1バイト、2バイト、4バイト、または8バイトに整列されているかどうかを知る方法がありません。これをコード化するには、おそらく長さ決定プロトコルを使用し、値が正しいことを確認するためのパックとアンパックコードの両方を使用して、整列の問題を排除します。 – WhozCraig

+0

あなたはライトなんだよ!しかし、そのままにしておくと、私は潜在的にどのような欠点に遭遇する可能性がありますか? – joaocandre

+0

@WhozCraig 2つの異なるプログラム間でデータを共有するためにUnixソケットとして使用していますが、それは問題になるでしょうか? – joaocandre

9

@timrauはかなり正確にコアの問題は(アライメント/梱包)ここにあるものを説明したが、私は提案されたソリューションのファンではありません。

doubleからなるコードでMESSAGEと記述しました。しかし、メモリ内の実際のデータ構造のサイズはsizeof(char) + sizeof(double)ではなく、であり、がコアの問題です。

提案された解決策は、重要なビットを埋め込む前に、MESSAGE構造のビットのすべてを単にクリアすることを示唆しています。私が持っている問題は、意味論的なものとテクニカルなものの両方です。ワイヤを通って送られるデータ構造のサイズは、あなたがコードでモデル化したものの正確な表現ではありません。つまり、chardoubleを送信しているだけではなく、chardoubleとその他のクラフト(パディング)を送信しています。

私の提案は、あなたのコードでモデル化したものだけを取り除くことです。

ありアライメントとパディングをオフにするC++には直接のサポートはありませんが、私の知るすべてのコンパイラがNバイトにデータ構造を整列させるための簡単なメカニズムを提供:

#pragma pack (push, 1) 

typedef struct{ 
    char type;  
    double value; 
} MESSAGE; 

#pragma pack (pop) 

をこれはMESSAGEを行いますデータ構造正確にあなたのコードでモデル化したもの、パディングなし。これにより、memsetが不必要になり、正確にsizeof(char) + sizeof(double)バイトが送信されます。

+0

これはおそらく基本的な質問ですが、この構造体が1バイト整列にパックされていても、受信側(ソケットの反対側)はそれをどのように知っていますか? – joaocandre

+0

クライアントには同じ構造体定義が必要です。パックしなかった場合と同じです。 –

+0

これをすばやくやらなければならない場合は、これが私が取るアプローチです。もし私がそれを移植可能でなければ*、私はおそらくメンバーを直列化する時間を過ごすでしょう。しかし、これは今でも私の議決権を得て、それに応じてそれを持っています。私が見た限りでは、OPの要件には十分です。 – WhozCraig

関連する問題