Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"points to uninitialised byte(s)" Valgrind errors

I've been using Valgrind to look for memory leaks in my code, and while no memory leaks are being found, some errors are reported all of them originating at a single function/class method:

==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)

The sendMsg(const char _type, const double _value), that the errors are pointing at, is part of unix_socket class:

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

I don't see what is the problem. Where exactly are the uninitialized values? Or should I just ignore the errors reported by Valgrind?

like image 749
joaocandre Avatar asked Oct 14 '13 16:10

joaocandre


People also ask

How do you calculate error in Valgrind?

If you compile your program with the -g flag, Valgrind will show you the function names and line numbers where errors occur. Sometimes the actual bug occurs on a different line (particularly for uninitialized value errors) but the line number Valgrind tells you is a good starting point.

What do valgrind errors mean?

Valgrind reports two types of issues: memory errors and memory leaks. When a program dynamically allocates memory and forgets to later free it, it creates a leak. A memory leak generally won't cause a program to misbehave, crash, or give wrong answers, and is not an urgent situation.

How does Valgrind Memcheck work?

Valgrind works by doing a just-in-time (JIT) translation of the input program into an equivalent version that has additional checking. For the memcheck tool, this means it literally looks at the x86 code in the executable, and detects what instructions represent memory accesses.

What is Memcheck?

Memcheck is a memory error detector. It can detect the following problems that are common in C and C++ programs. Accessing memory you shouldn't, e.g. overrunning and underrunning heap blocks, overrunning the top of the stack, and accessing memory after it has been freed.


1 Answers

Although @timrau has described quite correctly what the core problem is here (alignment/packing), I'm not a fan of the proposed solution.

You have described a MESSAGE in your code as consisting of a char and a double. The size of the actual data structure in memory however is not sizeof(char) + sizeof(double), and that is the core problem.

The proposed solution suggests simply clearing out all of the bits of the MESSAGE structure before filling in the important bits. The problem I have with that is both a semantic one a technical one -- the size of the data structure sent down the wire is not an accurate representation of what you modeled in the code. In other words, you're not just sending a char and a double -- you're sending a char, a double and some other cruft (padding).

My suggestion is to get rid of the cruft and send only what you modeled in your code.

There is no direct support in C++ to turn off alignment and padding, but all compilers I'm aware of provide a simple mechanism to align data structures to N bytes:

#pragma pack (push, 1)

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

#pragma pack (pop)

This will make the MESSAGE data structure exactly what you've modeled in your code, with no padding. Doing this makes the memset unnecesarry, and you'll send exactly sizeof(char) + sizeof(double) bytes down the wire.

like image 104
John Dibling Avatar answered Sep 28 '22 09:09

John Dibling