C++ Vectors and struct pointers - c++

My struct has a vector of integers. However, when dynamically creating an instance of the struct, I can't seem to access the vector.
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
typedef struct {
vector<int> intList;
} astruct;
int main()
{
astruct* myStruct = (astruct*) malloc(sizeof(astruct));
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
free(myStruct);
return 0;
}
Attempting to add 100 to the struct's vector crashes the program. Hello world! is never shown. What's going on?

Your vector is never initialized as you simply cast an allocated memory region to a astruct*, therefor the constructor of your struct and as consequence the constructor of std::vecotr is never called. Use the new operator instead.
astruct* myStruct = new astruct();
myStruct->intList.push_back(100);
delete myStruct;

You should not use malloc()/free() in C++ program, especially for creating C++ object, unless you know what you are doing. So use new/delete instead:
int main()
{
astruct* myStruct = new astruct;
myStruct->intList.push_back(100);
cout << "Hello world!" << endl;
delete(myStruct);
return 0;
}

Related

Issue on using multiple structures by pointers cause crash on program executing

Hello I noticed this weird issue when using multiple pointer structures at the same time.
Can somebody explain to me what is causing it ?
#include <iostream>
using namespace std;
typedef struct A{
int x;
}a;
int main()
{
a *a1, *a2;
a1->x = 3;
cout << a1->x << endl; // display "3"
a2->x = 2;
cout << a2->x << endl; // ...does not display "2" ???
return 0;
}
Before assigning the values to your pointers, the pointers have to be initialized properly.
a *a1, *a2;
These pointers are not initialized. They point to some random location in memory.
The "new" keyword allocates memory for your structure.
You can use it like this:
a *a1 = new A, *a2 = new A;

C++ why does new keyword works and malloc does not?

I'm learning about pointers and structures and I ran into this hard to understand the problem for me.
I have created this simple program for testing purpose:
#include <iostream>
struct testStructure
{
int a = 0;
int b = 0;
int c = 400;
};
int main()
{
struct testStructure* testStruct;
testStruct = new testSctructure;
std::cout << testStruct->c;
delete testStruct;
return 0;
}
the above program works just fine, it prints the value 400. But when i try to do it with malloc:
#include <iostream>
struct testStructure
{
int a = 0;
int b = 0;
int c = 400;
};
int main()
{
struct testStructure* testStruct;
testStruct = (testStructure*)malloc(sizeof testStructure);
std::cout << testStruct->c;
free(testStruct);
return 0;
}
it gives me this value:
-842150451
Why?
The above examples were written and build in Visual Studio 2019.
I know that in C++ you should almost always want to use new keyword but I wanted to experiment a bit.
new initializes the allocated memory with the class' constructor (which is implicit in this this case).
malloc performs no initialization, it just allocates a portion of memory. Reading uninitiazlied memory will have undefined behavior.
Here's how your second example can be made to work. In general, this is not a recommended way of working with C++, but there are some valid use cases.
#include <cstdlib>
#include <iostream>
struct testStructure {
int a = 0;
int b = 0;
int c = 400;
};
int main() {
auto testStruct_memory = std::malloc(sizeof(testStructure));
// In-place constructor.
auto testStruct = new(testStruct_memory) testStructure();
std::cout << testStruct->c << "\n";
// In-place destructor.
testStruct->~testStructure();
std::free(testStruct_memory);
}
In the case of malloc, you allocated a block of memory, but did not create an object. The testStructure constructor was not called.
You could call the constructor on the memory area with a placement new:
char* ptr = malloc(sizeof testStructure);
testStruct = new(ptr) testStructure;
but this is hard to read, confusing, hard to maintain, and fraught with risk. For example, you need
to free() not delete ptr
you need to similarly explicitly call the destructor.
So, not recommended.

How to create a vector with an initial size by using a custom constructor and without calling the destructor? [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 4 years ago.
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0x\n", v.num);
cout << "\n---------------\n";
cout << "END OF PROGRAM!\n";
cout << "---------------\n\n";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5)); (This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int) function and running it on every single object in the vector? (Of course changing malloc into realloc).
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), []() { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
Rule of three
Stop using std::endl
Why is “using namespace std” considered bad practice?
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.

c++ memory access violation

I am learning C++ and I am having quite a lot of trouble with my current assignment. I have completed a good amount of it so far. However I have been making very slow progress of late due to what I think is my poor understanding of what is going on behind the scenes.
What I am trying to do in the following code is:
Get two separate values (Bullet damage). Done.
Create a dynamic array. Done.
Fill a part (that is the size of a modulus of a random number between 1 and 10) of said dynamic array with one value and the rest with the other in a random order. Here I am having trouble.
Clean up the memory used by said dynamic array. Done.
The error I get is as follows:
Unhandled exception at 0x00a323e3 in Class 3.exe: 0xC0000005: Access
violation reading location 0xcdcdcdcd.
I'm pretty sure that the error occurs when I try to set ammoArray[i] to a value. But I don't know why it's giving it to me, my code compiles fine. I played around with it a bit and in one case I got it to store the memory addresses of bDamage and sDamage and then print out the memory addresses of each element of the array. What I want it to do is store the values held by bDamage and sDamage.
Now for my question:
Why won't ammoArray store the values of bDamage and sDamage instead of the memory addresses of the array's elements? And How do I get it to store them?
Here is my Main.cpp:
#include <cstdlib>
#include "Ammunition.h"
#include "AmmunitionManager.h"
#include "Bullet.h"
#include "Game.h"
#include "Pistol.h"
#include "Player.h"
#include "Point.h"
#include "Shell.h"
#include "Shotgun.h"
#include "WeaponManager.h"
#include "Weapons.h"
using namespace std;
void main()
{
Ammunition amVar;
AmmunitionManager *var = new AmmunitionManager();
amVar.setBDamage(6);
amVar.setSDamage(2);
var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());
system("PAUSE");
}
Here is the .h file of the class in question:
#ifndef AMMUNITIONMANAGER_H
#define AMMUNITIONMANAGER_H
#include "Point.h"
#include "Ammunition.h"
class AmmunitionManager
{
public:
AmmunitionManager();
AmmunitionManager(int,int);
~AmmunitionManager();
void FillAmmoArray(int,int);
private:
Ammunition Ammo;
int **ammoArray;
};
#endif
Here is the .cpp file of the class in question:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include "AmmunitionManager.h"
#include "Point.h"
#include "Ammunition.h"
using namespace std;
AmmunitionManager::AmmunitionManager()
{
}
AmmunitionManager::AmmunitionManager(int sDamage,int bDamage)
:Ammo(sDamage,bDamage)
{
cout << "Filling ammo reservoir." << endl;
ammoArray = new int* [10];
}
void AmmunitionManager::FillAmmoArray(int sDamage,int bDamage)
{
srand(time(NULL));
int *holdS = &sDamage;
int *holdB = &bDamage;
if(ammoArray)
{
for(int i = 0;i < 9;i++)
{
int randC = rand() % 2 + 1;
if(randC == 1)
{
cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
ammoArray[i] = holdS;
cout << "Is: " << ammoArray[i] << endl;
}
if(randC == 2)
{
cout << "Was: " << ammoArray[i] << endl;//I am getting the error here.
ammoArray[i] = holdB;
cout << "Is: " << ammoArray[i] << endl;
}
}
}
}
AmmunitionManager::~AmmunitionManager()
{
*ammoArray = 0;
if(ammoArray)
{
delete [] ammoArray;
}
}
Why won't ammoArray store the values of bDamage and sDamage instead of the memory addresses of the array's elements?
Because you said it should store addresses.
Here is a pointer to a pointer:
int **ammoArray;
and here is an array of pointers:
ammoArray = new int* [10];
And How do I get it to store them?
By doing this instead:
int *ammoArray;
and this:
ammoArray = new int [10];
and adjusting FillAmmoArray accordingly.
The default constructor should look like this:
AmmunitionManager::AmmunitionManager()
: ammoArray(nullptr)
{
}
The destructor should look like this:
AmmunitionManager::~AmmunitionManager()
{
delete [] ammoArray;
}
And you should only call srand once.
It's usually done at the beginning of main.
I'm not getting any errors (VS2013). But the values stored are the addresses of sDamage and bDamage.
Did you properly use AmmunitionManager(int sDamage,int bDamage) as a constructor for creating the AmmunitionManager object? From what I'm seeing, you're not.
Apart from that, may I ask why you're using exotic constructs such as **ammoArray instead of e.g. a simple vector<int>? I'm guessing it's part of your assignment, but I'm asking just to make sure I'm not missing anything.
I called the object like this:
int _tmain(int argc, _TCHAR* argv[])
{
AmmunitionManager* tc = new AmmunitionManager(5,10);
tc->FillAmmoArray(10,10);
return 0;
}
The problem is that you initialize AmmunitionManager with the default constructor:
AmmunitionManager *var = new AmmunitionManager();
In you default constructor you do nothing so ammoArray may contain any value.
It is better to initialize all the data to their default values:
AmmunitionManager::AmmunitionManager() : Ammo(), ammoArray(NULL/* or nullptr for C++11 */)
{
}
Now if you call for
var->FillAmmoArray(amVar.getSDamage(),amVar.getBDamage());
It will exit immediately since ammoArray is NULL.
Or probably you want to initialize ammoArray anyway, so the default constructor should have its initialization as well:
AmmunitionManager::AmmunitionManager() : Ammo()
{
ammoArray = new int* [10];
}
Also srand should be called only once, so better to place this code
srand(time(NULL));
in the main() or any other module which is guaranteed to be executed only once.
In the destructor, there is no need to zero *ammoArray=0, it actually puts 0 at the first element of that array (and that's it), you anyway delete it. And imagine that ammoArray is NULL, accessing *ammoArray would cause another segmentation fault.
Also there is no need to check for ammoArray beibg NULL before deleting it. The standard allows to 'delete' NULL pointers. delete will just return without doing nothing.
General note
It is better to use (safer and easier to maintain) std::vector instead of (dynamic) arrays and smart pointers instead of flat ones.
It's a bit tricky answering without building and debugging, but the first thing that strikes me are: Why are you using pointers (*) to int throughout?
Why don't you just have the array as a pointer:
int *ammoArray;
and make the other int-instances (remove the pointers - * and the address-of's (&))?
Regards

C++ how to use a pointer which has been created in a subroutine

or Mrs.,
in C++, I'm thinking about using a subroutine to define all my pointers first declared in my main body. I know it can be done by using functions to return one pointer each time. Hence, I still want to do it in a subroutine. I googled much and haven't found a answer yet. Your help is appreciated.
An sample c++ code is as:
#include <iostream>
using namespace std;
void testsub(int* k3d)
{
k3d= new int [10];
cout<<"test 0 "<<k3d[0]<<endl;
}
int main ()
{
int* i3d=0;
testsub(i3d);
cout<<"test 1 "<<i3d[0]<<endl;
}
I hope the i3d in the main body can be used after the dummy pointer k3d has been defined in the subroutine.
Thanks a lot in advance.
The pointer needs to be passed in by reference, otherwise you're just changing a local copy of that pointer.
void testsub(int*& k3d)
Also you need to call delete[] after the coutstatement, to avoid memory leaks:
delete [] i3d;
Alternatively, you could return a pointer from a subroutine.
#include <iostream>
int* testsub()
{
int* ptr = new int[10];
std::cout << "test 0 " << ptr[0] << std::endl;
return ptr;
}
int main()
{
int *i3d = testsub();
cout << "test 1 " << i3d[0] << endl;
delete[] i3d;
return 0;
}
Or use a std::vector to hold a collection of integers. In this case you don't need to worry about memory allocations/deallocations too.
#include <vector>
#include <iostream>
int main()
{
std::vector<int> i3d(10);
std::cout << "test 1 " << i3d[0] << std::endl;
return 0;
}