2013-10-14 3 views
8

내 코드에서 메모리 누수를 찾기 위해 Valgrind을 사용했지만 메모리 누수가없는 동안 일부 오류는 모두 하나의 함수/클래스 메소드 :"초기화되지 않은 바이트 (들) 가리 킵니다."Valgrind 오류

//... 
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; 
} 

나는 문제가 무엇인지 볼 수 없습니다 : 오류가 가리키는 것을

sendMsg(const char _type, const double _value)
==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) 

, unix_socket 클래스의 일부이다. 초기화되지 않은 값은 정확히 어디에 있습니까? 아니면 Valgrind가보고 한 오류를 무시해야합니까? MESSAGE 구조체에

답변

13

룩은 :

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

인해 데이터 구조 배향에 value의 어드레스 워드 크기의 복수의 어드레스에 정렬하도록 강요 될 수있다. 따라서 사용되지 않는 여러 바이트는 MESSAGE::typeMESSAGE::value 사이에 채워집니다. 그것들은 Valgrind에 의해 초기화되지 않고보고 된 바이트입니다.

해결 방법으로 전체 구조체를 강제로 memset()으로 초기화 할 수 있습니다.

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

대안으로 바이트 벡터에 구조체를 압축하여 보내고 각 요소의 정확한 크기로 조인다. 구조체 형태로 와이어를 통해 구조를 전송하는 것은 절대로 큰 아이디어가 아닙니다.현재 메커니즘을 읽는 클라이언트는 패딩 구조가 무엇인지 알 수 없기 때문에 결과적으로 'value'가 1 바이트, 2 바이트, 4 바이트 또는 8 바이트로 정렬되는지 여부를 알 수 없습니다 . 이 코드를 작성하려면 길이 결정 프로토콜을 사용하고 값이 올바른지 확인하여 팩 및 압축 해제 코드를 모두 가져야 정렬 문제가 해결됩니다. – WhozCraig

+0

당신은 라이트입니다. 그러나 그대로두면 어떤 단점이 발생할 수 있습니까? – joaocandre

+0

@WhozCraig 두 개의 다른 프로그램간에 데이터를 공유하기 위해 Unix 소켓으로 사용하고 있습니다. 문제가 될만한가? – joaocandre

9

@timrau 매우 정확하게 핵심 문제 (정렬/포장) 여기에 무엇인지 설명했지만, 나는 제안 된 솔루션의 팬이 아니에요.

코드에 MESSAGEchardouble으로 구성한 것으로 설명했습니다. 그러나 메모리에있는 실제 데이터 구조의 크기는 sizeof(char) + sizeof(double)이 아니며 이 핵심 문제입니다.

제안 된 솔루션은 중요한 비트를 채우기 전에 MESSAGE 구조의 모든 비트를 단순히 지우는 것을 제안합니다. 내가 가지고있는 문제는 의미 론적 하나의 기술적 인 문제입니다. 전선 아래로 보내진 데이터 구조의 크기는 코드에서 모델링 한 것을 정확하게 표현한 것이 아닙니다. 즉, chardouble 만 보내는 것이 아니라 char, double 및 기타 크래프트 (패딩)를 보내는 것입니다.

내 제안은 cruft를 제거하고 코드에서 모델링 한 것만 전송하는 것입니다.

가 정렬 및 패딩을 해제하는 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