I am fairly new to C++ and I keep getting segmentation fault with pointer assignment with code similar to the following, I know it means I'm accessing memory that hasn't been allocated, but I don't see where:
I have two classes:
class ClassA{ //class a decl.
ClassB** oArray;
unsigned int x;
public:
ClassA(unsigned int X);
void oMember(ClassB* classb);
}
ClassA::ClassA(unsigned int X){ //Constructor for class a
x = X;
oArray = new ClassB* [x];
for (unsigned int i = 0; i < x; i++){
oArray = NULL;
}
}
class ClassB{ //rough decl of class B
public:
getId();
}
I have a class member function that takes in a pointer to another class like this:
void ClassA::oMember(ClassB* classb){
unsigned int cID = classb.getId(); //defined in class b
oArray[cID] = classb; //if cID is less than x defined in constructor, is this legal?
}
I just want to point the cIDth member of the array to classb.
I keep getting segmentation fault with an assignment similar to the above. I don't quite know why, I printed the cID and it is definitely less than the size of the array we declared in ClassA's constructor.
Why is that assignment illegal, or why am I getting a segmentation fault?
As we realized in the chat, I just record the problem here for the reference.
The problem lies in the piece
RegisteredVMs = new VendingMachine *[nVendingMachines];
for (unsigned int i = 0; i < nVendingMachines; i++){
RegisteredVMs = NULL;
}
RegisteredVMs is allocated and immediately set to NULL.
This pointer is accessed later in the VMregister() function which causes the seg. fault.
Pointers are hard and very error-prone. Use them only if there is no other way. Since this is a homework problem and since you says you have no say on the interface, I see that you have to use them.
I think you should change your ClassA to
class ClassA{
std::map<int, std::shared_ptr<ClassB> > mMap;
public:
ClassA();
};
Now class A doesn't need to know the array size and mMap will ensure that you don't have very sparse arrays.
I think classb.getId() should be classb->getId() instead as long as classb is a pointer. Well, that should be compiler error and I don't think it is the reason you get segmentation faults.
Are you sure you instantiated ClassA with that particular constructor? If not, the x and oArray may not be initialised.
I do not have your code. But as I modified your code segment to be following, I find no segmentation faults nor compiler warnings.
class ClassB {
public:
int getId();
};
class ClassA {
ClassB** oArray;
unsigned int x;
public:
ClassA(unsigned int X);
void oMember(ClassB* classb);
};
int ClassB::getId() {
return 0;
}
ClassA::ClassA(unsigned int X) {
x = X;
oArray = new ClassB* [x];
}
void ClassA::oMember(ClassB* classb) {
unsigned int cID = classb->getId();
oArray[cID] = classb;
}
int main(int argc, char** argv) {
ClassA a(12);
ClassB b;
a.oMember(&b);
return 0;
}
Related
Please refer to this code first:
#include <iostream>
class parent_int{
public:
virtual int get_int() const=0;
virtual void increment_int()=0;
};
class a_int: public parent_int{
public:
int a;
a_int(int _a=0): a(_a){}
virtual int get_int()const override{return a;}
virtual void increment_int()override{a+=1;}
};
class b_int:public parent_int{
public:
int b;
b_int(int _b=0): b(_b){}
virtual int get_int() const override{return b;}
virtual void increment_int() override{b+=2;}
};
int main(){
int n=10;
parent_int **a = new parent_int*[10];
for(int i=0;i<n;i++)
{
if(rand()%2==0)
a[i] = new a_int(i);
else
a[i] = new b_int(i);
}
parent_int **alt_a = new parent_int*[10];
for(int i=0;i<n;i++)
{
//?alt_a[i] = ;
*(alt_a[i]) = *(a[i]);
alt_a[i]->increment_int();
}
for(int i=0;i<n;i++)
{
std::cout<<alt_a[i]->get_int()
<<" "<<a[i]->get_int()<<std::endl;
}
}
My question-
Is there a way by which I can copy my objects in
**alt_a from **a such that even when I make changes to my objects in **alt_a the objects of **a are unaffected?
Constraints-
I am using rand() here is to signify that there is no
way of knowing whether the *a points to a_int or b_int.
The parent function should remain a pure virtual function and should not have any constructors? And even if I place a constructor here I don't think how it will aid me?
This code snippet is just a representation of a problem that I am facing in my C++ project so I cannot take into consideration any changes in the design of my program. I need to use double pointers and in the same way as highlighted in the program.
Things that I have tried -
Just equating alt_a[i] = a[i] without de-referencing , this enables me to run my program but again the changes that I make in alt_a[i] is also represented in a[i]
I need to declare a 2D array as the member variable of a class. I can't use STL (so, no vector), and I've been asked to avoid double/triple pointers. I want to be able to reference elements in this 2D array using subscripting notation, e.g. arr[0][0]. The array also must be declared on the heap due to its size.
Due to the requirements I have, none of the existing answers on StackOverflow meet my needs.
What I've been trying to do is:
class MyClass {
public:
MyClass() : arr(new int[1000][2]) {}
// other stuff here
private:
int arr[1000][2];
};
The error I get after compiling that class is "cannot initialize a parameter of type int * with an lvalue of type int[1000][2]". Clearly, I can solve this by using pointer syntax, but, as mentioned above, I've been asked to use "array syntax" for code clarity. I was hoping someone with a better understanding of C++ could explain how to use "array syntax".
Of course you can do this without double/triple pointers. You can even do this without use of any pointers in the class declaration. But first lets look at the more common approach. A 2D array is a simple extension of a 1D array.
Starting off with the standard way this is done for a 1D array of 1000 ints w/o using vector. The pointer, arr, is on the stack but points to an array of 1000 ints on the heap.
class MyClass {
public:
MyClass() : arr(new int[1000]) {}
private:
int *arr;
};
Elements are accessed the usual way. For instance arr[0]=42;
Extending this to a 2D array in the heap is a simple extension of the above.
You need to declare the member variable as a pointer to a 1D array instead of the basic type.
class MyClass {
public:
MyClass() : arr(new int[1000][2]) {}
private:
int (*arr)[2];
};
Similarly, you can refer to elements of the 2D array the usual way: arr[0][0]=42;
Finally, there is the approach that completely eliminates pointers except the one required for the new. Here we initialize a reference. The trick is to add a third level to new, the [1] so that the *new returns an object that is the actual 2D int array. Structurally, it is no different than what the pointer version above does but lets us directly initialize a reference to a 2D int array. It's certainly not a common idiom so I'd stick with the ptr approach.
class MyClass {
public:
MyClass() : arr(*new int[1][1000][2]) {}
~MyClass() {delete[] arr;}
//private: // to test
int(&arr)[1000][2];
};
int main()
{
MyClass obj;
obj.arr[2][1] = 42;
}
When your class has an array in it, and you use new to create a new instance of that class, that array is on the heap. You can still access the array with arr[i][j].
Why not do something like this?
class myClass {
public:
int arr[1000][2];
};
int main() {
myClass* test = new myClass;
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 2; j++) {
test->arr[i][j] = 5;
}
}
}
You can use 2 classes to achieve this.
class BaseArray {
public:
int& operator[](int x) { return this->arr[x]; }
int operator[](int index) const { return this->arr[index]; }
int arr[2];
};
class myClass {
public:
myClass() {}
~myClass() {}
BaseArray& operator[](int index) { return this->arr[index]; }
BaseArray operator[](int index) const { return this->arr[index]; }
BaseArray arr[1000];
};
Optionally use can use templates to make this class more dynamic.
template<class TYPE, int arraySize>
class BaseArray {
public:
TYPE& operator[](int x) { return this->arr[x]; }
TYPE operator[](int index) const { return this->arr[index]; }
TYPE arr[arraySize];
};
template<class TYPE, int dim1, int dim2>
class myClass {
public:
myClass() {}
~myClass() {}
BaseArray<TYPE, dim2>& operator[](int index) { return this->arr[index]; }
BaseArray<TYPE, dim2> operator[](int index) const { return this->arr[index]; }
BaseArray<TYPE, dim2> arr[dim1];
};
int main()
{
myClass<int, 1000, 2> myArray;
}
EDIT
When you provide the array dimentions int arr[1000][2]; the variable will automatically be allocated in the stack. If the array needs to be fully dynamic, you can just use a double pointer int** arr = { nullptr }; and initialize it at the constructor as shown below.
class myClass {
public:
myClass()
{
arr = new int* [1000];
for (int i = 0; i < 1000; ++i)
arr[i] = new int[2];
}
~myClass()
{
/* Make sure to delete or else it might flag a memory error. */
for (int i = 0; i < 1000; ++i)
delete[] arr[i];
delete[] arr;
}
int** arr = { nullptr };
};
class Class
{
public:
Class(array[3][3]) //the constructor
{
this->array = array
}
array[3][3];
};
int main()
{
array[3][3] = {...initialization...};
Class object(array[3][3]);
}
I want to make an object, which uses the 2d array and modifies it. I know that C arrays are just pointers to an address, but I couldn't pass it in the constructor no matter how many *, & or [] I write.
The most clever thing I could think of is making an array of POINTERS in the class, and assigning each pointer, to the address of the original array's element via for loop, but then every time I want to modify, or read from the array in main, I have to write for example *array[2][1] = 3.
Any clever solution?
If I finally got the question correctly, you can use a reference to an array:
struct Class {
Class(int (&array)[3][3]) : array_(array)
{}
void set11(int value) {
array_[1][1] = value;
}
int (&array_)[3][3];
};
int main() {
int array[3][3]{};
Class object(array);
object.set11(99);
std::cout << array[1][1]; // Prints 99
}
If that's not what you want, please clarify your question.
Here's how to declare a pointer in your class that can point to the array in main.
class Class
{
public:
Class(int (*array)[3])
{
this->array = array;
}
int (*array)[3];
};
int main()
{
int array[3][3] = { ... };
Class object(array);
}
C++ newbie here. This may be stupid but I am getting segmentation fault while assigning value to struct in a class. Any pointers?
#include <iostream>
#include<string>
using namespace std;
struct s { std::string s;};
class A {
public:
A(){}
~A(){}
struct s *ss[10];
};
int main(){
A a;
a.ss[0]->s = "test";
cout<<a.ss[0]->s<<endl;
return 0;
}
The pointer a.ss[0] is not allocated.
You could for example allocate it in the constructor of class A, like this:
A(){ ss[0] = new s; }
I'm not sure what the purpose of your code is.
P.S.: Don't forget to delete the allocated memory once it is not needed anymore. For example:
~A(){ delete ss[0]; }
Alternatively, as LogicStuff pointed out, you can rewrite the array of pointers to a regular array, like this:
struct s ss[10];
struct s *ss[10];
What this line declares is an array of 10 pointers to struct s, not 10 objects of type struct s. Those 10 pointers point nowhere, to make them useful you have to actually allocate memory for and create those object (and clean them up when you're done).
This is where constructors and destructors come in handy:
class A {
public:
A()
{
for(int i = 0; i < 10; ++i)
{
ss[i] = new s;
}
}
~A()
{
for(int i = 0; i < 10; ++i)
{
delete ss[i];
}
}
struct s *ss[10];
};
Now each of those 10 pointers in your array point to valid struct s objects, so you can safely access them:
A a;
a.ss[0]->s = "test";
When you say
/*struct*/ s *ss[10]; // P.S. you don't need "struct" here as in C
the compiler understands that it should reserve space in your class for 10 pointers to objects of type s. It doesn't make sure that those pointers point to anything valid, though.
Actually, the safest thing would be to avoid raw arrays entirely and use a vector. Your life will be much easier.
struct A {
// note no need to declare default ctor and dtor here
std::vector<s> ss{10}; // initialize with 10 default-constructed strings
};
// then in main()
A a;
a.ss[0].s = "test";
s* p = &ss[0]; // if you need a pointer; fine so long as vector doesn't change
I'm writing a class for the Arduino. It's been going well so far, but I'm sort of stuck now...
I have declared an int array in my class
class myClass
{
public: MyClass(int size);
private:
int _intArray[];
};
When I initialize the class MyClass myClass1(5) I need the array to look like this {0,0,0,0,0}.
My question: what do I need to do so that the array contains 'size' amount of zeros?
MyClass::MyClass(int size)
{
//what goes here to dynamically initialize the array
for(int i=0; i < size; i++) _intArray[i] = 0;
}
Edit: Following up on various replies below, Arduino does not include the standard library so unfortunately std::vector is not an option
Your code as I'm writing this:
class myClass
{
public: MyClass(int size);
private:
int _intArray[];
};
The declaration of _intArray is not valid C++: a raw array needs to have a size specified at compile time.
You can instead instead use a std::vector:
class myClass
{
public:
MyClass( int size )
: intArray_( size ) // Vector of given size with zero-valued elements.
{}
private:
std::vector<int> intArray_;
};
Note 1: some compilers may allow your original code as a language extension, in order to support the "struct hack" (that's a C technique that's not necessary in C++).
Note 2: I've changed the name of your member. Generally underscores at the start of names can be problematic because they may conflict with names from the C++ implementation.
Cheers & hth.,
You should use a std::vector.
class myCLass {
public:
myClass(int size)
: intarray(size) {
for(int i = 0; i < size; i++) intarray[i] = 0;
}
private:
std::vector<int> intarray;
};
You should really use vectors as others have suggested. A work-around could be as shown (in case you do not want to use memcpy or a loop).
This would be useful if you have a really huge array. Note that it would add a level of indirection to access the array.
class myClass
{
public:
myClass(){
mt = T(); // value initialize.
}
private:
struct T{
int _intArray[10];
} mt;
};
int main(){
myClass m;
}
I'll try the following:
class myClass
{
public:
MyClass(int size);
~MyClass();
private:
int* _intArray;
};
MyClass::MyClass(int size) {
_intArray = new int[size];
for (int i=0; i<size; ++i) _intArray[i] =0; // or use memset ...
}
MyClass::~MyClass() {
delete[] _intArray;
}
Or, even better, use a STL vector instead ...
you can use another hack basing on a string value and then populate a limited size array
check this :
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git