10

我一直在使用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 报告的错误?

4

2 回答 2

14

MESSAGE结构:

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

由于数据结构对齐,value的地址可能被迫对齐到字长倍数的地址。MESSAGE::type因此,在和之间填充了几个未使用的字节MESSAGE::value。这些是未初始化的字节,因此由 Valgrind 报告。

作为一种解决方法,您可以强制初始化整个结构memset()

MESSAGE msg;
memset(&msg, 0, sizeof(MESSAGE));
msg.type=_type;
msg.value=_value;
于 2013-10-14T16:42:47.620 回答
10

尽管@timrau 已经非常正确地描述了这里的核心问题(对齐/打包),但我不喜欢所提出的解决方案。

MESSAGE在代码中将 a 描述为由 achar和 a组成double。然而,内存中实际数据结构的大小却不是sizeof(char) + sizeof(double)是核心问题。

MESSAGE建议的解决方案建议在填充重要位之前简单地清除结构的所有位。我遇到的问题既是语义问题也是技术问题——通过网络发送的数据结构的大小并不能准确表示您在代码中建模的内容。换句话说,您不只是发送 achar和 a double——您正在发送 a char、 adouble和其他一些杂乱无章的东西(填充)。

我的建议是摆脱杂乱无章的内容,只发送您在代码中建模的内容。

C++ 中没有直接支持关闭对齐和填充,但是我知道的所有编译器都提供了一种简单的机制来将数据结构与N字节对齐:

#pragma pack (push, 1)

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

#pragma pack (pop)

这将使MESSAGE数据结构与您在代码中建模的完全一样,没有填充。这样做是memset不必要的,您将通过网络发送准确sizeof(char) + sizeof(double)的字节。

于 2013-10-14T17:13:09.887 回答