While I was trying to create an array in c++ class, there arose a problem while using the constructor. Here is the code:
int stacksize = 100;
int* buffer;
int stackpointer[3]= {-1, -1, -1};
public:
threestack(int stacksize_u)
{
int buffer_u[stacksize_u*3];
this->buffer = buffer_u;
this->stacksize = stacksize_u;
}
threestack()
{
int buffer_u[(this->stacksize)*3];
this->buffer = buffer_u;
}
This actually did not work. When I create the array in the declaration, however, it worked:
int stacksize = 100;
int buffer[300];
int stackpointer[3]= {-1, -1, -1};
Can anybody tell me what is wrong while I was using the constructor?
PSS: Here is the whole class and test program:
class threestack
{
int stacksize = 100;
int* buffer;
int stackpointer[3]= {-1, -1, -1};
public:
threestack(int stacksize_u)
{
int buffer_u[stacksize_u*3];
this->buffer = buffer_u;
this->stacksize = stacksize_u;
}
threestack()
{
int buffer_u[(this->stacksize)*3];
this->buffer = buffer_u;
}
bool push(int stacknum, int value);
bool pop(int stacknum);
int peek(int stacknum);
bool empty(int stacknum);
};
bool threestack::push(int stacknum, int value)
{
if(stackpointer[stacknum-1]+1 >= stacksize)
{
cout<<"Plz do not try to push to a full stack"<<endl;
// printf("stackpointer = %d\n", stackpointer[stacknum-1]);
return 0;
}
else
{
stackpointer[stacknum-1]++;
buffer[stackpointer[stacknum-1]+(stacknum-1)*stacksize] = value;
return 1;
}
}
int threestack::peek(int stacknum)
{
if(stackpointer[stacknum-1] < 0)
{
printf("No element in stack now.\n");
return 0;
}
else
{
printf("stackpointer = %d\n", stackpointer[stacknum-1]);
return buffer[stackpointer[stacknum-1]+(stacknum-1)*stacksize];
}
}
bool threestack::pop(int stacknum)
{
if(stackpointer[stacknum-1] < 0)
{
printf("Plz do not try to pop an empty stack.\n");
return 0;
}
else
{
stackpointer[stacknum-1]--;
}
return 1;
}
bool threestack::empty(int stacknum)
{
if(stackpointer[stacknum-1] < 0)
{
return true;
}
else
{
return false;
}
}
int main(int argc, const char * argv[])
{
threestack test;
test.push(1,5);
// test.pop(1);
// test.pop(1);
int i;
for(i=0; i<101; i++)
{
test.push(2, i);
printf("%d\n", test.peek(2));
}
cout<<endl;
printf("The top of stack 1 is %d\n", test.peek(1));
// std::cout << "Hello, World!\n";
return 0;
}
C++ arrays have a fixed size at compile time.
This is why your test module works - the size (=300) is known at compile time.
That's mandatory because the size of an array is in fact part of it's type, implying that
the type of int[1] is very different from int[2].
Yet it is not known when you kind of "dynamically" create the array in the constructor.
The way out is allocating dynamic memory using the new and delete [] operators.
Even better, try to use shared_ptr, unique_ptr or auto_ptr.
This
int* buffer;
is not a declaration of an array. It is a declaration of a pointer to int.
In constructor
threestack(int stacksize_u)
{
int buffer_u[stacksize_u*3];
this->buffer = buffer_u;
this->stacksize = stacksize_u;
}
all these two statements
int buffer_u[stacksize_u*3];
this->buffer = buffer_u;
are invalid. Firest of all sizes of arrays shall be constant expressions. Secondly you assign adrress of the first element of a local array to pointer buffer. After exiting from the constructor this address will be invalid because the local array will be destroyed.
You should either allocate dynamically array using operator new and assigning its value to data member buffer or use container std::vector instead of the dynamically allocated array.
Related
I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment
I'm trying to assign a value to array.
Type of arrayPointer is int*. The code below is minimal reproducible code.
#include <iostream>
using namespace std;
class ExtendableArray;
class ElementRef {
private:
ExtendableArray *intArrayRef; //pointer to the array
int index; // index of this element
public:
ElementRef(ExtendableArray &theArray, int i);
ElementRef &operator=(int val);
operator int() const;
};
class ExtendableArray {
private:
int *arrayPointer; // integer array pointer
int size; // the size of array
public:
ExtendableArray();
ElementRef operator[](int i);
friend class ElementRef;
};
int main() {
ExtendableArray arr;
printf("arr[1]: %d\n", (int) arr[1]);
arr[0] = 5;
return 0;
}
ElementRef::ElementRef(ExtendableArray &theArray, int i) {
ExtendableArray *ref = &theArray;
intArrayRef = ref;
index = i;
}
ElementRef &ElementRef::operator=(int val) {
printf("0: %d\n", intArrayRef->arrayPointer[0]);
intArrayRef->arrayPointer[0] = 5;
printf("0: %d\n", intArrayRef->arrayPointer[0]);
printf("INDEX: %d\n", index);
intArrayRef->arrayPointer[index] = 5;
}
ElementRef::operator int() const {
return this->intArrayRef->arrayPointer[this->index];
}
ExtendableArray::ExtendableArray() {
this->arrayPointer = new int[2]{0};
this->size = 2;
}
ElementRef ExtendableArray::operator[](int i) {
ElementRef ref = ElementRef(*this, i);
return ref;
}
The code above crashes with
0: 0
0: 5
INDEX: 0
Process finished with exit code 4
When I attach debugger, debugger points intArrayRef->arrayPointer[index] = 5;
How can this happen? I mean, why does constant index works while non-constant index crashes?
That's just how arrays in c++ work, they have a constant index. You will have to use another class for your problem, i would recommend
std::vectory<Type T>
which will allow you to add elements, store them and also in comparison to c++ Lists, elements of a vector can be adressed by index which feels more like an array with variable length.
The documentation on vectors can be found here.
I forgot return statement, and it results in a crash. When I change code to return *this, it works.
Compiler show warning, but I couldn't see warnings as I pressed debug button on CLion
ElementRef &ElementRef::operator=(int val) {
printf("0: %d\n", intArrayRef->arrayPointer[0]);
intArrayRef->arrayPointer[0] = 5;
printf("0: %d\n", intArrayRef->arrayPointer[0]);
printf("INDEX: %d\n", index);
intArrayRef->arrayPointer[index] = 5;
return *this;
}
In my understanding, under usual conditions, array is being allocated memory at compile time, but what happens when array is a member variable, and there is pretty much nothing to allocate memory to during compilation. Does it get implicitly dynamically-allocated, when instance of that class is created?
class Arr{
public:
int arr[10];
};
Arr doSomething(Arr &arg){
return arg; //copy of arg created; 'copy=new int[10]' at this point?
}
int main(){
Arr temp;
doSomething(temp);
//if returned object's array was dynamically initialized
//will it result the array in temp being released twice?
}
UPD. In my case, situation rises when I try to subract A-B where B>A. In these cases I can access array to read from it, but modifying its values leads to garbage. Moreover, final output in main is fine. Here's full code:
#include <iostream>
using namespace std;
const int MAX_ARRAY_SIZE=256;
char* getOperatorIndex(char* equationString);
bool isOperator(char characterDec);
int* toIntArray(char* firstInA, char* lastInA, int* firstInB);
class Number{
int* firstInNumber;
int* lastInNumber;
int number[MAX_ARRAY_SIZE];
public:
Number();
~Number();
bool operator<(Number& b);
int& operator[](int index);
Number operator-(Number& b);
void print();
int length(){return lastInNumber-firstInNumber;}
int*& lastPtr(){return lastInNumber;}
int*& firstPtr(){return firstInNumber;}
};
Number::Number(){
firstInNumber=number;
lastInNumber=number;
}
Number::~Number(){
cout<<"number destroyed"<<endl;
}
int& Number::operator[](int index){
return number[index];
}
bool Number::operator<(Number& b){
if(length()>b.length())return false;
if(length()<b.length())return true;
for(int a=0;a<length();++a){
if(number[a]>b[a])return false;
if(number[a]<b[a])return true;
}
return false;
}
void Number::print(){
for(int a=0; a<=length(); ++a){
cout<<number[a];
}
cout<<endl;
}
Number Number::operator-(Number& b){
Number result;
if(*this < b)
{
result=b-*this;
cout<<*result.lastPtr()<<endl;
result.print();
*result.lastPtr()*=-1; // GARBAGE HERE
cout<<*result.lastPtr()<<endl;
return result;
}
result[0]=0;
for(int q=0; q<=length(); ++q)
{
if(b.length()-q >= 0)
{
result[q]+=(*this)[length()-q]-b[b.length()-q];
if(result[q] < 0)
{
result[q]+=10;
result[q+1]=-1;
}
else
{
result[q+1]=0;
}
}
else
{
result[q]+=(*this)[length()-q];
}
++result.lastPtr();
}
do{
--result.lastPtr();
}while(!*result.lastPtr());
return result;
}
int main(){
char equationArray[MAX_ARRAY_SIZE*2+1]; // operandA(<=256) operator(1) operandB(<=256)
Number a,b;
cin>>equationArray;
char* operatorPtr=getOperatorIndex(equationArray);
a.lastPtr()=toIntArray(equationArray, operatorPtr, a.firstPtr());
b.lastPtr()=toIntArray(operatorPtr+1, operatorPtr+strlen(operatorPtr), b.firstPtr());
a.print();
b.print();
Number c;
switch(*operatorPtr){
case '-':
c=a-b;
break;
}
c.print();
}
char* getOperatorIndex(char* equationString){
while(!isOperator(*++equationString));
return equationString;
}
bool isOperator(char characterDec){
if(characterDec>='*' & characterDec<='/')return true;
return false;
}
int* toIntArray(char* firstInA, char* lastInA, int* firstInB){
while(lastInA-firstInA>0){
*firstInB=*firstInA-'0';
++firstInB;
++firstInA;
}
return --firstInB;
}
All data members of a class have the same storage-duration as the class' object created. Hence in:
int main(){
Arr temp;
doSomething(temp);
}
The data member temp.arr which is of type int[10]; also has automatic storage-duration.. (or what is inappropriately known as "stack object")
Arr doSomething(Arr &arg){
return arg; //copy of arg created; 'copy=new int[10]' at this point?
}
No, there is no heap allocation here. rather a member-wise copy by the implicit copy constructor. See How are C++ array members handled in copy control functions?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have a application that is suppose to store graphic elements. I am having an issue where I cant access a variable in a structure. Here is what i have so far.
#include <crtdbg.h>
#include <string.h>
#include <stdio.h>
#include "CLib.h"
enum{ RUNNING = 1 };
struct Point
{
int x, y;
};
struct Line
{
Point start;
Point end;
};
struct GraphicElement
{
enum{ SIZE = 256 };
char name[SIZE];
CStash Lines; // a Stash of Lines
};
struct VectorGraphic
{
CStash Elements; // a Stash of GraphicElements
};
void AddGraphicElement(VectorGraphic*);
void ReportVectorGraphic(VectorGraphic*);
void CleanUpVectorGraphic(VectorGraphic*);
VectorGraphic Image;
int main()
{
char response;
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
// it's a Stash of GraphicElements initialize(&(Image.Elements),sizeof(GraphicElement));
while (RUNNING)
{
printf("\nPlease select an option:\n");
printf("1. Add a Graphic Element\n");
printf("2. List the Graphic Elements\n");
printf("q. Quit\n");
printf("CHOICE: ");
fflush(stdin);
scanf("%c", &response);
switch (response)
{
case '1':AddGraphicElement(&Image); break;
case '2':ReportVectorGraphic(&Image); break;
case 'q':CleanUpVectorGraphic(&Image); return 0;
default:printf("Please enter a valid option\n");
}
printf("\n");
}
return 0;
}
void AddGraphicElement(VectorGraphic* pImage){
int i = 0, counter = 0;
int xPointStart = 0, yPointStart = 0;
int xPointEnd = 0, yPointEnd = 0;
char name[50];
int lineNumber = 0;
GraphicElement *pElement = nullptr;
Line *pLine = nullptr;
initialize(&(Image.Elements), sizeof(GraphicElement));
printf("ADDING A Graphic Element\n");
printf("Please enter the name of the new GraphicElement(<256 characters): ");
fflush(stdin);
scanf("\n%[^\n]s", &name);
fflush(stdin);
strcpy(pElement->name,name);
Anytime I try assigning strcpy(pElement->name,name); it tells me access violation.
The two other files im working with that cannot be changed and are from a textbook called Thinking in C++.
//: C04:CLib.cpp {O}
// Implementation of example C-like library
// Declare structure and functions:
#include "CLib.h"
#include <iostream>
#include <cassert>
using namespace std;
// Quantity of elements to add
// when increasing storage:
const int increment = 100;
void initialize(CStash* s, int sz)
{
s->size = sz;
s->quantity = 0;
s->storage = nullptr;
s->next = 0;
}
int add(CStash* s, const void* element)
{
if (s->next >= s->quantity) //Enough space left?
inflate(s, increment);
// Copy element into storage,
// starting at next empty space:
int startBytes = s->next * s->size;
unsigned char* e = (unsigned char*)element;
for (int i = 0; i < s->size; i++)
s->storage[startBytes + i] = e[i];
s->next++;
return(s->next - 1); // Index number
}
void* fetch(CStash* s, int index)
{
// Check index boundaries:
assert(0 <= index);
if (index >= s->next)
return 0; // To indicate the end
// Produce pointer to desired element:
return &(s->storage[index * s->size]);
}
int count(CStash* s)
{
return s->next; // Elements in CStash
}
void inflate(CStash* s, int increase)
{
assert(increase > 0);
int newQuantity = s->quantity + increase;
int newBytes = newQuantity * s->size;
int oldBytes = s->quantity * s->size;
unsigned char* b = new unsigned char[newBytes];
for (int i = 0; i < oldBytes; i++)
b[i] = s->storage[i]; // Copy old to new
delete[](s->storage); // Old storage
s->storage = b; // Point to new memory
s->quantity = newQuantity;
}
void cleanup(CStash* s)
{
if (s->storage != 0)
{
cout << "freeing storage" << endl;
delete[]s->storage;
}
} ///:~
and the .h file...
//: C04:CLib.h
// Header file for a C-like library
// An array-like entity created at runtime
typedef struct CStashTag {
int size; // Size of each space
int quantity; // Number of storage spaces
int next; // Next empty space
unsigned char* storage;// Dynamically allocated array of bytes
} CStash;
void initialize(CStash* s, int size);
void cleanup(CStash* s);
int add(CStash* s, const void* element);
void* fetch(CStash* s, int index);
int count(CStash* s);
void inflate(CStash* s, int increase);
///:~
GraphicElement *pElement = nullptr;
// ...
strcpy(pElement->name,name);
Somewhere between the top line and bottom line above you need to allocate memory for pElement.
pElement = new GraphicElement();
Also, consider using a std::shared_ptr instead of a raw pointer, given you tagged this C++.
I have written the following code in C++, however found out that I have to convert it in C. I am not C or even C++ programmer, please help.
Can someone help me change this method to C directives, specifically vector implementation, following will not compile I have removed complexity to keep it simple. Thanks in anticipation.
__declspec(dllexport) std::vector<MY_STRUCT> WINAPI ABC(char *strVal)
{
MY_STRUCT f;
std::vector<MY_STRUCT> list = std::vector<MY_STRUCT>();
while (*dddd)
{ /*do the following for every feature in license file*/
f.attrib_num = fi.attrib_num;
f.attrib_lic = fi.attrib_lic;
list.push_back(f);
} /* end while(conf) */
dddd++;
printf("\n");
} /* end while (*dddd) */
return flist;
}
Here is implementation (also usage) of dynamic array of structs in C. You can adapt it to your structure; I used to post it on code review before
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int ID;
char * name;
} Student;
// array of structs
typedef struct
{
Student *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize)
{
int i = 0;
// Allocate initial space
a->array = malloc(initialSize * sizeof(Student));
a->used = 0; // no elements used
a->size = initialSize; // available nr of elements
// Initialize all values of the array to 0
for(i = 0; i<initialSize; i++)
{
memset(&a->array[i],0,sizeof(Student));
}
}
// Add element to array
void addElement(Array *a, Student element)
{
int i = 0;
if (a->used == a->size)
{
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(Student));
// Initialize the last/new elements of the reallocated array
for(i = a->used; i<a->size; i++)
{
memset(&a->array[i],0,sizeof(Student));
}
}
// Copy name
a->array[a->used].name = (char*)malloc(strlen(element.name) + 1);
strcpy(a->array[a->used].name, element.name);
// Copy ID
a->array[a->used].ID=element.ID;
a->used++;
}
void freeArray(Array *a)
{
int i = 0;
// Free all name variables of each array element first
for(i=0; i<a->used; i++)
{
free(a->array[i].name);
a->array[i].name=NULL;
}
// Now free the array
free(a->array);
a->array = NULL;
a->used = 0;
a->size = 0;
}
int main(int argc, const char * argv[])
{
Array a;
Student x,y,z;
x.ID = 20;
x.name=malloc(strlen("stud1") + 1);
strcpy(x.name,"stud1");
y.ID = 30;
y.name=malloc(strlen("student2") + 1);
strcpy(y.name,"student2");
z.ID = 40;
z.name=malloc(strlen("student3") + 1);
strcpy(z.name,"student3");
// Init array, don't forget
initArray(&a, 5);
// Add elements
addElement(&a, x);
addElement(&a, y);
addElement(&a, z);
// Print elements
printf("%d\n", a.array[0].ID);
printf("%s\n", a.array[0].name);
printf("%d\n", a.array[1].ID);
printf("%s\n", a.array[1].name);
printf("%d\n", a.array[2].ID);
printf("%s\n", a.array[2].name);
// Free array
// don't forget
freeArray(&a);
free(x.name);
free(y.name);
free(z.name);
return 0;
}