GithubHelp home page GithubHelp logo

bump.hpp's People

Contributors

polynominal avatar

Watchers

 avatar  avatar

bump.hpp's Issues

The use of the removeIf statement in World::Remove can read invalid data when the item is found and Removed while not being the last item

Hey,

I've been playing with the library, but i had a really hard time with it already, mostly related to memory issues but that is probably my own fault for not having used shared pointers for the item i passed to world::add.

Anyway i'm finally at a point where i might be able to use it without memory errors reported in valgrind after a very long weekend of debugging but i did encounter one more issue and i actually found the cause as well.

Consider the following example to illustrate the problem:

#include <CollisionResponses.hpp>
#include <World.hpp>
#include <stdio.h>
#include <string.h>

using namespace plugin::physics::bump;

World world;

class testclass
{
public:
    Item* bumpItem;
};

int main(int argv, char** args)
{
    auto item1 = std::make_shared<testclass>();
    auto item2 = std::make_shared<testclass>();
    auto item3 = std::make_shared<testclass>();
    item1.get()->bumpItem = world.Add(item1, {11,11,11,11});
    item2.get()->bumpItem = world.Add(item2, {11,11,11,11});
    item2.get()->bumpItem = world.Add(item3, {11,11,11,11});
    printf("World Count before %d\n", world.CountItems());
    world.Remove(item1.get()->bumpItem);
    printf("World Count after %d\n", world.CountItems());
}

this will cause the wrong read of memory reported in valgrind

kubuntu@kubuntu2204:~/dev$ valgrind ./test
==16498== Memcheck, a memory error detector
==16498== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16498== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==16498== Command: ./test
==16498== 
==16498== Invalid read of size 8
==16498==    at 0x112954: plugin::util::UserData::GetRaw() (UserData.hpp:67)
==16498==    by 0x1105FC: auto plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}::operator()<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > >(std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >&) const (World.cpp:246)
==16498==    by 0x110635: bool __gnu_cxx::__ops::_Iter_pred<plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>::operator()<__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > > >(__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >) (predefined_ops.h:318)
==16498==    by 0x10FCD3: __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > > std::__remove_if<__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__ops::_Iter_pred<plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}> >(__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__ops::_Iter_pred<plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>) (stl_algo.h:822)
==16498==    by 0x10F757: __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > > std::remove_if<__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>(__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}) (stl_algo.h:894)
==16498==    by 0x10F436: bool removeIf<std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>(std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > >&, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}) (World.cpp:16)
==16498==    by 0x10DCA1: plugin::physics::bump::World::Remove(plugin::physics::bump::Item*) (World.cpp:245)
==16498==    by 0x10A5A5: main (test.cpp:141)
==16498==  Address 0x4de0db0 is 16 bytes inside a block of size 48 free'd
==16498==    at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16498==    by 0x10BF02: std::default_delete<plugin::physics::bump::Item>::operator()(plugin::physics::bump::Item*) const (unique_ptr.h:85)
==16498==    by 0x11E8C9: std::__uniq_ptr_impl<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >::reset(plugin::physics::bump::Item*) (unique_ptr.h:182)
==16498==    by 0x11C5CB: std::__uniq_ptr_impl<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >::operator=(std::__uniq_ptr_impl<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >&&) (unique_ptr.h:167)
==16498==    by 0x1190FC: std::__uniq_ptr_data<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item>, true, true>::operator=(std::__uniq_ptr_data<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item>, true, true>&&) (unique_ptr.h:212)
==16498==    by 0x11912A: std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >::operator=(std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >&&) (unique_ptr.h:371)
==16498==    by 0x10FD08: __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > > std::__remove_if<__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__ops::_Iter_pred<plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}> >(__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__ops::_Iter_pred<plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>) (stl_algo.h:824)
==16498==    by 0x10F757: __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > > std::remove_if<__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>(__gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, __gnu_cxx::__normal_iterator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >*, std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}) (stl_algo.h:894)
==16498==    by 0x10F436: bool removeIf<std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > >, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}>(std::vector<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> >, std::allocator<std::unique_ptr<plugin::physics::bump::Item, std::default_delete<plugin::physics::bump::Item> > > >&, plugin::physics::bump::World::Remove(plugin::physics::bump::Item*)::{lambda(auto:1&)#1}) (World.cpp:16)
==16498==    by 0x10DCA1: plugin::physics::bump::World::Remove(plugin::physics::bump::Item*) (World.cpp:245)
==16498==    by 0x10A5A5: main (test.cpp:141)
==16498==  Block was alloc'd at
==16498==    at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==16498==    by 0x114B80: std::_MakeUniq<plugin::physics::bump::Item>::__single_object std::make_unique<plugin::physics::bump::Item, plugin::util::UserData&, plugin::physics::bump::Rectangle&>(plugin::util::UserData&, plugin::physics::bump::Rectangle&) (unique_ptr.h:962)
==16498==    by 0x10DA04: plugin::physics::bump::World::Add(plugin::util::UserData, plugin::physics::bump::Rectangle) (World.cpp:208)
==16498==    by 0x10ADBC: plugin::physics::bump::Item* plugin::physics::bump::World::Add<testclass>(std::shared_ptr<testclass>, plugin::physics::bump::Rectangle) (World.hpp:113)
==16498==    by 0x10A458: main (test.cpp:138)
==16498== 
==16498== 
==16498== HEAP SUMMARY:
==16498==     in use at exit: 0 bytes in 0 blocks
==16498==   total heap usage: 15 allocs, 15 frees, 73,272 bytes allocated
==16498== 
==16498== All heap blocks were freed -- no leaks are possible
==16498== 
==16498== For lists of detected and suppressed errors, rerun with: -s
==16498== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
kubuntu@kubuntu2204:~/dev$ 

if you got 3 items in your world items list and you erase the 1st one, you'll actually get a memory error reported of an invalid read of size 8 on the GetRaw() function. I was baffled by this error and did not understand it at all initially, but what seems to happen is that the Remove statement makes Item invalid inside the lambda while actually executing the remove itself. The problem is the lambda passed to removeIf in World::Remove. basically this one :

return removeIf(items, [item](auto& candidate){
        return candidate->UserData.GetRaw() == item->UserData.GetRaw();
    });

as soon as the condition is true you'll get that error in that situation and the only culprit i see is being item being invalidated / pointing to something that got cleared / erased.

the solution i did to go around the issue is simple though, instead of passing the item to the lambda pass the rawpointer itself and compare against the raw pointer.

auto itemRawValue = item->UserData.GetRaw();
    return removeIf(items, [itemRawValue](auto& candidate) {
        return candidate->UserData.GetRaw() == itemRawValue;
    });

and the error is no more reported and the item(s) are cleared as well

kubuntu@kubuntu2204:~/dev$ valgrind ./test
==16574== Memcheck, a memory error detector
==16574== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16574== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==16574== Command: ./test
==16574== 
World Count before 3
World Count after 2
==16574== 
==16574== HEAP SUMMARY:
==16574==     in use at exit: 0 bytes in 0 blocks
==16574==   total heap usage: 16 allocs, 16 frees, 74,296 bytes allocated
==16574== 
==16574== All heap blocks were freed -- no leaks are possible
==16574== 
==16574== For lists of detected and suppressed errors, rerun with: -s
==16574== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
kubuntu@kubuntu2204:~/dev$ 

Now i do not understand the internal workings of std::remove_if and erase like in what way it all happens but it somehow caused this error to happen while doing the actual remove in combination with the unique pointers, it's also the reason i did not make a pull request with my change for it as i wanted to pass it by you first as you have a far better understanding of these things. The only things i go by are the valgrind memory reports and usually if there are errors reported it was caused by my own coding. I'm not sure if the error makes sense to you or not. It does explain however why in the other issue i made initially this error in the test code program went away by keeping a reference to item (like one of the workarounds i had suggested) but seems placing the removeif at the end was not the complete solution as item inside the lamba seems to become invalid during the remove itself or well at least the trying to get the rawdata using it

Project segfaults as soon as i link against libbump.a

Hi,

Do you perhaps know why my project segfaults as soon as i link against the created libbump.a ? I don't even have to call any functions from it, just linking it in segfaults the project.

I ran the project through valgrind and right before the segfault it reported these memory issues but i don't know if they are being caused due to something i did wrong like with CXXFLAGS or so or if there is an issue with the project ?

==23746==    at 0x117494: std::_Function_base::~_Function_base() (std_function.h:243)
==23746==    by 0x10D262: function (std_function.h:395)
==23746==    by 0x10D262: plugin::physics::bump::response::Cross::Resolve(plugin::physics::bump::CollisionResolution&, plugin::physics::bump::Collision*, plugin::physics::bump::Rectangle const&, math::vec2, std::function<bool (plugin::physics::bump::Item*, plugin::physics::bump::Item*, plugin::physics::bump::Collision*)>) [clone .cold] (CollisionResponse.cpp:28)
==23746==  Address 0x10 is not stack'd, malloc'd or (recently) free'd
==23746==
==23746==
==23746== Process terminating with default action of signal 11 (SIGSEGV)
==23746==  Access not within mapped region at address 0x10
==23746==    at 0x117494: std::_Function_base::~_Function_base() (std_function.h:243)
==23746==    by 0x10D262: function (std_function.h:395)
==23746==    by 0x10D262: plugin::physics::bump::response::Cross::Resolve(plugin::physics::bump::CollisionResolution&, plugin::physics::bump::Collision*, plugin::physics::bump::Rectangle const&, math::vec2, std::function<bool (plugin::physics::bump::Item*, plugin::physics::bump::Item*, plugin::physics::bump::Collision*)>) [clone .cold] (CollisionResponse.cpp:28)```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.