Reputation: 79
In my program, I am copying a vector<vector<int> >
to another as such:
#include <vector>
#include <cstdlib>
#include <cmath>
typedef std::vector<std::vector<int> > VVector;
VVector mix_genome(VVector mix_genome,
VVector g1,
VVector g2,
int gene_length)
{
VVector gbuilt = g1; // valgrind gets angry at this a bit...
for(int i = 0; i < 30; i++)
{
int syngamete_chance = std::floor(std::rand() % 100);
if(syngamete_chance <= 50)
{
gbuilt[i] = g2[i];
}
}
int mutation_chance = floor(rand() % 100);
if(mutation_chance <= 3)
{
int gene_num = floor(rand() % 30);
int act_num = floor(rand() % gene_length+1);
int rand_act = floor(rand() % 8);
gbuilt[gene_num][act_num] = rand_act;
}
return gbuilt;
}
This, after around 3 minutes of running the program (which every once in a while calls this function) results in a memory access error. Valgrind gives me the following information about this function: ==31557== Invalid write of size 4
and Address 0x10207e360 is 0 bytes after a block of size 16 alloc'd
If I disable the function and do not call it, the program appears not to crash. GDB gives me malloc: *** error for object 0x1068a6878: incorrect checksum for freed object - object was probably modified after being freed.
. The backtrace shows that it comes from operator=:
#13 0x000000010000f8d4 in std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::operator= (this=0x7fff5fbfe780, __x=@0x7fff5fbfeb50) at vector.tcc:140
I think this is resulting in other errors as well, though I am not sure.
EDIT:
Here is my Tick()
function which is also apparently contributing to this error.
int Creature::Tick() {
if(!dead) {
food--;
timeLasted++;
step++;
if(step > maxStep) {
step = 0;
}
if(cooldown > 0) {
cooldown--;
}
if(xpos > 178) {
events[EVENT_RIGHT_SEEN_EDGE_OF_SCREEN] = true;
}
else if(xpos < 20) {
events[EVENT_LEFT_SEEN_EDGE_OF_SCREEN] = true;
}
if(ypos > 179) {
events[EVENT_BOTTOM_SEEN_EDGE_OF_SCREEN] = true;
}
else if(ypos < 20) {
events[EVENT_TOP_SEEN_EDGE_OF_SCREEN] = true;
}
events[EVENT_NOTHING_HAPPENED] = true;
for(int z = 0; z < NUM_EVENTS-1; z++) {
if(events[z]) {
events[EVENT_NOTHING_HAPPENED] = false; // events[z] is true so something happened
}
}
for(int i = 0; i < NUM_EVENTS-1; i++) { // last event should always be "nothing happened"
if(events[i]) {
Action(genome[i][step]); // this has been ided by valgrind: invalid read size 4
events[i] = false;
}
}
if(!fighting && events[EVENT_NOTHING_HAPPENED]) {
Action(genome[EVENT_NOTHING_HAPPENED][step]);
}
if(food < 0)
food = 0;
if(food > maxFood)
food = maxFood;
if(food == 0) {
lifetime -= 5;
}
if(xpos > 200-bodySize) {
xpos = 200-bodySize;
}
else if(xpos < 0) {
xpos = 0;
}
if(ypos > 200-bodySize) {
ypos = 200-bodySize;
}
else if(ypos < 0) {
ypos = 0;
}
}
return timeLasted;
}
Upvotes: 2
Views: 741
Reputation: 392954
Actually this might be the problem:
int act_num = floor(rand() % gene_length+1);
Did you mean
int act_num = rand() % (gene_length+1);
?
This would roughly match the last complaint by valgrind: invalid write at line ~(207-188) == ~+19 inside mix_genome
.
Here's the relevant part decrufted:
==31557== Invalid write of size 4
==31557== at 0x100001C43: mix_genome(...) (Game.h:207)
...
==31557== Address 0x10207e360 is 0 bytes after a block of size 16 alloc'd
==31557== by 0x10000CB10: std::vector<...>::vector(std::vector<...> const&) (stl_vector.h:233)
==31557== by 0x100001AD3: mix_genome(std::vector<...>, ...) (Game.h:188)
OLD ANSWER TEXT
Although it's currently unknown whether this could still be relevant, the original analysis also showed other ways how you can "read" valgrind's diagnostics:
Your problem is not with the vectors. It looks like you have a stale reference (potentially a threading bug).
FPS: 0 # of Creatures: 414 # of Food: 348 ==31557== Invalid read of size 4
==31557== at 0x1000016BC: Creature::Tick() (Creature.h:204)
What this tells me is that in Tick()
you're updating some kind of stats (including the FPS that gets printed on the console?). Apparently, this refers to an address:
==31557== Address 0x100095980 is 0 bytes after a block of size 16 alloc'd
==31557== at 0xC658: malloc (vg_replace_malloc.c:295)
...
(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&) (stl_vector.h:233)
==31557== by 0x10000CCA2: Creature::Creature(Creature const&) (Creature.h:52)
So, likely it holds a reference to something that got freed/reallocated.
Note that when vectors resize, they can invalidate all existing references, pointers and/or iterators. To avoid this,
vector::reserve
can be used to avoid having to reallocate on expected growthboost::stable_vector
Edit Indeed mix_genome
appears to write invalid addresses too. Reading more of your valgrind log.
Upvotes: 3
Reputation: 112
In this cicle
for(int i = 0; i < 30; i++)
{
int syngamete_chance = std::floor(std::rand() % 100);
if(syngamete_chance <= 50)
{
gbuilt[i] = g2[i];
}
}
if i > gbuilt.size(), you must to use gbuilt.push_back(g2[i]). In other way not allocated memory for this item.
Upvotes: 0