Null reference exception c++ - c++-cli

I keep getting this error in the console:
Unhandled exception: System.NullReferenceException
Here's the code:
class Car {
public:
int X;
int Y;
};
class SpecificCar : public Car {
};
class Container {
public:
int AmountOfCars = 0;
Car **cars = nullptr;
void AddCar(Car *ptr);
};
void Container::AddCar(Car *ptr) {
if(AmountOfCars == 0) {
cars[0] = ptr; //Debbuger says that the problem in question is located here
AmountOfCars++;
}
int main() {
Container container;
Car *ptr = new SpecificCar;
ptr->X = 1;
ptr->Y = 5;
container.AddCar(ptr);
}

While your Container by design isn't storing Cars, it still has to store pointers to cars. You'll have to come up with a method. The Standard offers std::vector<Car> as well as std::vector<Car*> but you're free to come up with anything else. Still, if you don't want the Standard methods, it's really up to you what else you want to do.

Car **cars is not a dynamic container, it's a pointer to a memory region. What you did there is just utterly wrong. You still have to allocate an array of pointers to be able to fill data there, such as
cars = new Car*[5];
With that you can address with indices from 0 to 4 inside array cars[]. Yet again this is not dynamic, your best bet is an std::vector<Car*>, if you want to go your own ways then malloc()/realloc(), maybe linked listing if you really want to bother with it.

The problem is that, in class Container, you defined a member cars initialized to nullptr.
The best way to fix the issue is to use a std::vector<Car*> for cars. If you absolutely don't want to use a vector (why ?), in class Container, you may replace:
Car **cars = nullptr;
by something like:
static const int MAX_AMOUNT_OF_CARS = 100;
Car* cars[MAX_AMOUNT_OF_CARS];
which will define a proper array of Car*; then, you will be able to use cars[0], cars[i], ...

I figure you're trying to teach yourself about memory management. I've rewritten your class and AddCar() to be more what you want. Accessing or removing a car and deleting the container are left as an exercise for the student. (Look at this as pseudo-code. I haven't compiled or run it.)
class Container
{
Car ** cars_ = nullptr;
int capacity_ = 0; // how much room we have for car pointers
int AmountOfCars_ = 0; // how many car pointers we actually contain
public:
int AmountOfCars() const { return AmountOfCars_; }
void AddCar(Car *ptr);
};
void Container::AddCar(Car *ptr)
{
if ( AmountOfCars_ + 1 > capacity_ ) // ensure we have capacity for another Car *
{
if ( capacity_ == 0 ) // if we have none set to 2, so we'll initially allocate room for 4
capacity_ = 2;
int newcapacity = capacity_ * 2; // double the capacity
Cars ** newcars = new Car*[ newcapacity ]; // allocate a new pointer array
memcpy( newcars, cars_, capacity_ * sizeof(Car*) ); // we're just moving pointers
delete cars_; // get rid of the old pointer array
cars_ = newcars; // point to the new pointer array
capacity_ = newcapacity; // update the capacity
}
++AmountOfCars_; // increase the number of cars
cars[ AmountOfCars_ ] = ptr; // and copy the pointer into the slot
}

Related

`const int* const int` initialisation with function

I want to define a constant array of constants at every MPI node using C++03. M_chunk_sizes defines the size of matrix that will be passed to other nodes and won't be changed during the runtime.
int* define_chunk_sizes( int S, int world) {
int out[world];
double quotient = static_cast<double> (S) / world;
int maj = ceil(quotient);
for (int i =0; i < world - 1; i++)
out[i] = maj;
out[world-1] = maj + (S - maj*world);
return out;
}
int main() {
const int M = 999; // rows
int world_size = 4;
const int* const M_chunk_sizes = define_chunk_sizes(M, world_size);
}
But i get a warning: address of stack memory associated with local variable 'out' returned [-Wreturn-stack-address]
return out;.
What is the right way of doing this?
funciton local variables(stack varibales) will go out of scope and life once function returns.
you have use dynamic memory management operators, so allocate memory to out using
new
and relase memory using
delete
once you done with it.

Adding aging to boids simulation

I am working on expanding this sketch: http://www.openprocessing.org/sketch/11045
Trying to add aging to boids agents using frameCount.
I initialise ArrayList with age inbuilt:
boids = new ArrayList();
for (int i = 0; i < boidNum; i++) {
Agent boid = new Agent(random(width), random(height), 1, round(frameCount + random(300, 400)));
boids.add(boid);
}
Then retrieve it :
Agent(float posX, float posY, int t, int a) {
mass = 5.0;
location = new PVector(posX, posY);
vel = new PVector(random(-5,5), random(-5, 5));
acc = new PVector();
type = t;
wdelta = 0.0;
action = 0;
age = a;
}
I want to use something like this for the living cycle :
if (frameCount != age) {
age = age - 1;
}
if (frameCount == age) {
boids.remove(this);
}
But I'm not sure where in the code I should put it.
Also is this the best way to do it, or am I overcomplicating things?
Update:
I wrote a new method:
void boid(ArrayList boids) {
for (int i = 0; i < boids.size(); i++) {
if (frameCount >= age) {
boids.remove(this);
}
}
}
which is being called from:
void steer(ArrayList boids, ArrayList predators, ArrayList landscape) {
if (type == 1) boid(boids); ...
It sounds like you would want to put that code in the Agent class, after you do the updating and drawing of the Agent- taking a quick look at the code, that's probably the run() function in the Agent class.
But I'm not totally sure why you're comparing each Agent's age with the frameCount. The frameCount variable just tells you how long the sketch has been running. You if statement kills any birds that have the same age as the sketch, which doesn't make any sense.
Instead, you need to have two variables in your Agent class: the age variable that starts at 0 and increments by one each frame, and a maxAge variable that stores the age at which the Agent should be removed.
If you want some friendly advice though, I'd really recommend starting over from scratch with your own code instead of trying to modify an existing one, especially if you aren't really sure how the code works yet. It might seem like you're saving time by using existing code, but if you don't really know how code works yet, you'll definitely save yourself a bunch of headaches by writing it yourself. Up to you though.

C General Protection Fault trying to access object in array

In my program, I store objective-c objects in a c array, like this
va_start(list, o);
retval->objs = malloc(SIZE * count);
retval->objs[0] = (__bridge void *)o;
for (int i = 1; i < count; i++)
{
id o = va_arg(list, id);
retval->objs[i] = (__bridge void *)o;
}
va_end(list);
(count is a number containing how many objects will be added; that value is always correct)
objs is a void ** and is part of retval, which is a pointer to a struct. As of now, SIZE is defined as 100. Increasing and decreasing that had no effect.
As you can see, I bridge o to a void *, as I have to. objs, when all the objects are added, contains 3 objective-c objects. When I try to access a value like this
void *obj = CLArrayObjectAtIndex(_arr, ind);
return (__bridge id)obj;
this is the CLArrayObjectAtIndex() function
void *CLArrayObjectAtIndex(CLArrayType *arr, int ind)
{
void *o = arr->objs[ind];
if (o)
return o;
else
perror("Attempt to access NULL object or index out of bounds."), abort();
}
if the index (ind) is 0, it works. If the index is 1, the program crashes when it returns in main. If the index is 2, the program crashes as soon as I try to access it. If the index is 1, the value returned above is correct, but when the program crashes on return it is nil.
If the index is 1, the EXC_BAD_ACCESS code is 1; if the index is 2, the code is EXC_I386_GPFLT, a general protection fault. I already checked here for an explanation of this exception, although I couldn't find anything helpful. So, does anybody see why this error may be occurring?
when you store obj-c objects in C array don't just bridge cast them since that way arc doesn't know they are still used and releases them. __bridge_retain them so they stay around later, when you free the array __bridge_transfer them to give them back to ARC
also don't define size as 100.. sizeof(id) should work. You only need to store pointers

cli::array<int> to iterator in c++-cli

I have managed class with function:
int DoSomething(cli::array<int>^ values) { .. }
In DoSomething I must call native function:
template <class It>
int Calculate(It beg, It end) {..}
Which iterator to use?
You'll want to use a pinning pointer to the managed array. This will fix the array in memory (i.e. make it so the garbage collector can't move it) and then you can treat it as a native array. Below is a sample using your methods.
Take note, that you need to finish using the array before the pinning pointer goes out of scope--once the pinning pointer goes out of scope, the managed array is no longer pinned, and the garbage collector is free to move the array.
Also, take note that pinning the first element of the array causes the entire managed array to be pinned (in general using a pinning pointer on one part of a managed object causes the entire managed object to be pinned).
template <class It> int Calculate(It beg, It end)
{
int sum = 0;
for (; beg != end; ++beg)
{
int i = *beg;
sum += i;
}
return sum;
}
int DoSomething(cli::array<int>^ values)
{
int numValues = values->Length;
pin_ptr<int> pNativeValuesBegin = &values[0];
int * pBegin = pNativeValuesBegin;
int * pEnd = pBegin + numValues;
return Calculate(pBegin, pEnd);
}
int main(array<System::String ^> ^args)
{
array<int> ^ values = gcnew array<int> { 1, 2, 3, 4, 5 };
int sum = DoSomething(values);
System::Console::WriteLine(sum);
return 0;
}

error C3698: 'CreerLevel::Mur ^' : impossible d'utiliser ce type comme argument de 'nouveau'

i have create one class and i need to use it with vector.
ref class Mur
{
public:
int debutX, debutY;
int finX, finY;
Mur (){}
Mur(int debutX, int debutY) {
this->debutX = debutX;
this->debutY = debutY;
finX = 0;
finY = 0;
}
~Mur()
{
}
int getX() { return debutX; }
int getY() { return debutY; }
bool estFinit() {
return (finX==0);
}
void finir(int x, int y){
finX = x;
finY = y;
}
};
}
When i try to use it
std::vector<Mur^> vMurs;
...
vMurs.push_back(gcnew Mur(i,j));
Error come in file "xmemory" at line 52 but i don't know this file xD
The compiler is objecting because you're trying to store a managed object in an unmanaged class. That cannot work, the garbage collector needs to be able to find object references so it can properly collect garbage. And since it cannot find unmanaged objects, it cannot find the managed reference either.
I'd strongly advice to not use STL/CLR, it combines all the disadvantages of STL with those of the CLR. If you really, really want to use vector<> then gcroot<> can solve the problem. However, using System::Collections::Generic::List<> is by far the best solution.
using namespace System::Collections::Generic;
...
List<Mur^>^ vMurs = gcnew List<Mur^>;
...
vMurs->Add(gcnew Mur(i, j));
I agree with Alexandre C. If you want to use a vector, you could use the STL/CLR (http://msdn.microsoft.com/en-us/library/bb385954.aspx) vector.
Try using
std::vector<gcroot<Mur ^> > vMurs;
...
vMurs.push_back(gcnew Mur(i,j));