c++ - ==15341==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xb59007e0 at pc 0x8048ca7 bp 0xbfb47388 sp 0xbfb4737c -
i'm pretty new dynamic memory management , using fsanitise flag find problems memory management. cannot use vector store data - need use primitive arrays, "new" , "delete" manage heap objects.
i got following error when try run euclideanvectortester compiled program not sure problem is, enlighten me please?
weill % make g++ -std=c++14 -wall -werror -o2 -fsanitize=address -c euclideanvectortester.cpp g++ -std=c++14 -wall -werror -o2 -fsanitize=address -c euclideanvector.cpp g++ -fsanitize=address euclideanvectortester.o euclideanvector.o -o euclideanvectortester weill % ./euclideanvectortester 1 ================================================================= ==15341==error: addresssanitizer: heap-buffer-overflow on address 0xb59007e0 @ pc 0x8048ca7 bp 0xbfb47388 sp 0xbfb4737c write of size 8 @ 0xb59007e0 thread t0 #0 0x8048ca6 in main (/tmp_amd/kamen/export/kamen/3/z3386180/cs6771/evec/euclideanvectortester+0x8048ca6) #1 0xb6ecae45 in __libc_start_main (/lib/i386-linux-gnu/i686/cmov/libc.so.6+0x16e45) 0xb59007e0 located 0 bytes right of 16-byte region [0xb59007d0,0xb59007e0) allocated thread t0 here: #0 0xb722a4c4 in operator new[](unsigned int) (/usr/lib/libasan.so.1+0x524c4) #1 0x8048b9a in main (/tmp_amd/kamen/export/kamen/3/z3386180/cs6771/evec/euclideanvectortester+0x8048b9a) #2 0xb6ecae45 in __libc_start_main (/lib/i386-linux-gnu/i686/cmov/libc.so.6+0x16e45) #3 0x8048d8c (/tmp_amd/kamen/export/kamen/3/z3386180/cs6771/evec/euclideanvectortester+0x8048d8c) summary: addresssanitizer: heap-buffer-overflow ??:0 main shadow bytes around buggy address: 0x36b200a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b200b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b200c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b200d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b200e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x36b200f0: fa fa fa fa fa fa fa fa fa fa 00 00[fa]fa 04 fa 0x36b20100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b20110: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b20120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b20130: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x36b20140: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa shadow byte legend (one shadow byte represents 8 application bytes): addressable: 00 partially addressable: 01 02 03 04 05 06 07 heap left redzone: fa heap right redzone: fb freed heap region: fd stack left redzone: f1 stack mid redzone: f2 stack right redzone: f3 stack partial redzone: f4 stack after return: f5 stack use after scope: f8 global redzone: f9 global init order: f6 poisoned user: f7 contiguous container oob:fc asan internal: fe ==15341==aborting weill %
the euclideanvector.h file this:
#ifndef _euclideanvector_h #define _euclideanvector_h #include <iostream> #include <algorithm> namespace { class euclideanvector { public: /* * constructor takes number of dimensions (as unsigned int) no magnitudes, * sets magnitude in each dimension 0.0. default constructor, default value being 1. */ template <typename num> euclideanvector(const num dimensions = 1): euclideanvector(dimensions, 0.0) {}; // delegating constructor; default constructor takes in dimensions if there user input, otherwise dimensions = 1 if empty constructor // target constructor delegating constructor template <typename num1, typename num2> // numeric types of user input dimensions , magnitude static_cast unsigned int , double respectively euclideanvector(const num1 dimensions, const num2 magnitude){ // static cast unsigned int , assign dimensions_ dimensions_ = new unsigned int (static_cast<unsigned int>(dimensions)); // assign pointer "magnitude_" dynamically-allocated memory of new unnamed array<double> object of size "dimensions_" magnitude_ = new double [*dimensions_]; // fill array<double> object "magnitude_" number of "dimensions_" times, <double> value of "magnitude_" each dimension std::fill_n(magnitude_, dimensions_, static_cast<double>(magnitude)); } /* * destructor: ~euclideanvector * destructor deallocates memory acquired constructors. */ ~euclideanvector(); /* * member function: getmagnitude() * returns double containing number of dimensions in particular array. */ const double& getmagnitude () const; /* * member function: getnumdimensions() * returns unsigned int containing number of dimensions in particular vector. */ unsigned int getnumdimensions() const; private: /* here end of class private, * not accessible or intended use client */ unsigned int *dimensions_; double *magnitude_; //double normal_; }; } #endif
the euclideanvector.cpp file this:
#include "euclideanvector.h" #include <algorithm> #include <cmath> // sqrt #include <sstream> #include <iterator> namespace { unsigned int euclideanvector::getnumdimensions () const { return *dimensions_; } const double& euclideanvector::getmagnitude () const { return *magnitude_; } // destructor euclideanvector::~euclideanvector() { delete dimensions_; delete [] magnitude_; } }
and euclideanvectortester.cpp file this:
#include <iostream> #include <vector> #include <list> #include "euclideanvector.h" int main() { std::cout << "1" << std::endl; evec::euclideanvector a(2); std::cout << "2" << std::endl; std::cout << "3" << std::end; }
let me professor states has lot of inaccuracies (to least).
having said that, issue you've declared dimensions
unsigned int*
, yet you're using if plain unsigned int
here:
std::fill_n(magnitude_, dimensions_, static_cast<double>(magnitude));
the immediate fix this:
std::fill_n(magnitude_, *dimensions_, static_cast<double>(magnitude));
however, begs question of why simple unsigned int
needs pointer, , allocated using new
. there no reason this, using new
less efficient you're doing now.
if had declared dimensions_
this:
unsigned int dimensions_;
instead of being pointer, code assign dimensons_
becomes this:
// no call new done dimensions_ = static_cast<unsigned int>(dimensions); // no dereference of pointer needs done on 2 lines below magnitude_ = new double[dimensions_]; std::fill_n(magnitude_, dimensions_, static_cast<double>(magnitude));
no additional call allocator done, code instantly becomes more efficient.
in addition, destructor this:
euclideanvector::~euclideanvector() { delete magnitude_; }
but of stated, answer given fixes issue if use same main
program test with. if changed main
this:
even::euclideanvector a(2); even::euclideanvector b = a;
you run copy semantics being incorrect. again, fix above required make main
function work. change main
simple above example, , run more issues.
Comments
Post a Comment