我一直在使用 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报告的错误?
答案 0 :(得分:13)
查看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;
答案 1 :(得分:9)
尽管@timrau已经非常正确地描述了核心问题(对齐/打包),但我不是所提议解决方案的粉丝。
您已在代码中将MESSAGE
描述为由char
和double
组成。但是,内存中实际数据结构的大小不是sizeof(char) + sizeof(double)
,是的核心问题。
建议的解决方案建议在填写重要位之前简单地清除MESSAGE
结构的所有位。我遇到的问题是语义和技术问题 - 从线路发送的数据结构的大小并不能准确表示您在代码中建模的内容。换句话说,您不只是发送char
和double
- 您发送了char
,double
和其他一些(填充)。
我的建议是摆脱残骸,只发送你在代码中建模的东西。
C ++中没有直接支持来关闭对齐和填充,但我所知道的所有编译器都提供了一种简单的机制来将数据结构与N
字节对齐:
#pragma pack (push, 1)
typedef struct{
char type;
double value;
} MESSAGE;
#pragma pack (pop)
这将使MESSAGE
数据结构完全您在代码中建模的内容,没有填充。这样做会使memset
不必要,并且您将准确地发送sizeof(char) + sizeof(double)
字节。