Search code examples
c++valgrind

Valgrind: INVALID READ OF SIZE 1 in constructor


I am getting an invalid read of size 1 in the following function:

ubigint.cpp

ubigint::ubigint (unsigned long that){ 
   //DEBUGF ('~', this << " -> " << uvalue)
   ostringstream convert;  // stream for converting numbers to strings
   convert << that;  // output the number to the stream

    for(string::reverse_iterator rit = convert.str().rbegin(); rit != convert.str().rend(); rit++) // iterate through the string
    {
        ubig_value.push_back(*rit); // push the character
    }  
    size_t current_size = ubig_value.size();
    while(current_size != 0 && ubig_value.back() == '0')
    {
        ubig_value.pop_back();
        current_size--;
    }

}

ubigint.h

// $Id: ubigint.h,v 1.11 2016-03-24 19:43:57-07 - - $

#ifndef __UBIGINT_H__
#define __UBIGINT_H__

#include <exception>
#include <iostream>
#include <limits>
#include <utility>
using namespace std;

#include "debug.h"
#include "relops.h"

    class ubigint {
       friend ostream& operator<< (ostream&, const ubigint&);
       private:
          /*using unumber = unsigned long;
          unumber uvalue {};
          */
          using udigit_t = unsigned char; 
          using ubigvalue_t = vector<udigit_t>; 
          ubigvalue_t ubig_value;

       public:
          void multiply_by_2();
          void divide_by_2();

          ubigint() = default; // Need default ctor as well.
          ubigint (unsigned long);
          ubigint (const string&);

          ubigint operator+ (const ubigint&) const;
          ubigint operator- (const ubigint&) const;
          ubigint operator* (const ubigint&) const;
          ubigint operator/ (const ubigint&)const;
          ubigint operator% (const ubigint&) const;

          bool operator== (const ubigint&) const;
          bool operator<  (const ubigint&) const;


          //helper functions
          string vectorToString(ubigvalue_t& myVector)const;
    };

    #endif

Error Message:

==4025== Invalid read of size 1
==4025==    at 0x40309C: ubigint::ubigint(unsigned long) (ubigint.cpp:23)
==4025==    by 0x40412F: udivide(ubigint const&, ubigint) (ubigint.cpp:260)
==4025==    by 0x404418: ubigint::operator/(ubigint const&) const (ubigint.cpp:285)
==4025==    by 0x40709D: bigint::operator/(bigint const&) const (bigint.cpp:89)
==4025==    by 0x40CCEB: do_arith(iterstack<bigint>&, char) (main.cpp:35)
==4025==    by 0x40D58F: main (main.cpp:143)

I didn't put the other functions because I think that the cause of the problem is the constructor. I noticed that I was comparing ubig_value.back() against the integer 0. I changed it to char and that still didn't solve the problem. What is wrong with the constructor?. Line 23 is ubig_value.pop_back();. When I run the program without using valgrind, it runs properly.


Solution

  • convert.str() returns a temporary string instance, by value. Two calls to convert.str() produce different instances of string, so convert.str().rbegin() and convert.str().rend() do not form a valid range - they are iterators into different containers.

    Moreover, rit is a dangling iterator - the string it points into, being a temporary, is gone by the time the iterator is used.

    Therefore, your function exhibits undefined behavior.