Search code examples
c++linuxvectorudpinitialization

Vector is pointing to uninitialized bytes when used in recvfrom call


In a function that I am writing I am trying to return a pointer to a vector of unsigned chars. The relevant code is below.

std::vector<unsigned char> *ret = new std::vector<unsigned char>(buffSize,'0');
//Due to suggestions...
int n = recvfrom(fd_, ret, buffSize, &recvAddress, &sockSize);
//Forgot to include this in the original
ret->resize(n);
// display chars somehow just for testing
for(std::vector<unsigned char>::iterator it=ret->begin(); it<ret->end();it++)
{
    std::cout<<*it;
}
std::cout<<std::endl;
...
return ret;

When I run this through valgrind I get errors talking about how the buffer in recvfrom is pointing to uninitialized bytes. I've narrowed this down to the vector since I swapped it out for an unsigned char array and everything works fine. Any suggestions?

Edit 1: Fixed some of the code, was doing this from memory/notes with a problem that I was having at work. The reason I started to use valgrind was that I was getting a segmentation fault at that spot. I will double check what I was doing tomorrow.


Solution

  • This line is wrong:

    int n = recvfrom(fd_, ret, buffSize, &recvAddress, &sockSize);
    

    It should be:

    int n = recvfrom(fd_, &(*ret)[0], buffSize, 0, &recvAddress, &sockSize);
    

    You're reading data directly onto the std::vector data structure, which is typically 3 pointers (beginning, end, and end-of-storage). So, you're overwriting those 3 pointers with data received over the socket, and then you're overwriting random memory after the vector. The compiler doesn't complain because any pointer type (std::vector<char> * in this case) is implicitly convertible to a void* (the second parameter to recvfrom).

    You of course want to read data into the buffer pointed to by the vector, which is obtained by taking the address of its first element, namely &(*ret)[0]. We have to add the awkward parentheses because brackets [] have higher operator precedence than the unary dereferencing operator *.

    (Also note that you're missing the flags parameter to recvfrom() -- I'm assuming that was just a transcription error when writing this question, and I've now set that to 0 here.)