Class deconstructor and pointers - c++

We were writing a code in our university (learning about Object Oriented Program). We wrote this class and the issue is that, as per my understanding and our teacher the program should crash in the following condition, but in my case it doesn't.
The thing is this line is the culprit
DynamicArray d, f;
f = d;
according to him(rest of the code is attached), since when main ends, deconstructor deletes f and then goes for d, but since pointer was pointing to same mem location in both cases, now it should give error when it tries to delete it, since there is nothing there....but my compiler runs the code perfectly. I am using gcc compiler. Denconstructor at the end of class, rest is to fill dynamic array.
#include <iostream>
#include <ctime>
class DynamicArray{
private:
int *arr;
int size, cap; //cap is the physical size, size is number of elements
public:
DynamicArray(){
arr = nullptr;
size = cap = 0;
}
DynamicArray(int i){
cap = i;
size = 0;
arr = new int[cap];
}
void pushback(int j){
if(cap == 0){
arr = new int[cap];
arr[0] = j;
size++;
cap++;
}
else if(size < cap){
arr[size] = j;
size++;
}
else if(size == cap){
int *arr2 = new int[cap * 2];
int i;
cap *= 2;
for(i = 0; i < size; i++){
arr2[i] = arr[i];
}
arr2[i++] = j;
delete[] arr;
arr = arr2;
}
}
void print(){
for(int i = 0; i < size; i++)
std::cout << arr[i] << " ";
}
~DynamicArray(){
if(arr != nullptr)
delete[] arr;
}
};
int main(){
DynamicArray d, f;
srand(time(nullptr));
int n = rand() % 5;
for(int i = 0; i < n; i++){
d.pushback(rand() % 10);
}
f = d;
f.print();
std::cout << std::endl;
d.print();
return 0;
}

Your code causes so-called "undefined behaviour". Basically, that means anything can happen, including that nothing happens or that whatever happens isn't easily observable. For a more precise definition of "undefined behaviour", you'd have to check e.g. the C++ standard, but there are also many discussions concerning this term here.
Try running your code using e.g. valgrind, it will tell you that your code is broken.

Related

Valgrind errors from dynamically allocated arrays in C++

The program is aimed to take a dynamically allocated array and return a new dynamically allocated array with double the size that copies the values in the first one and leaves the rest uninitialized. However, it's getting valgrind errors in main(). Any suggestions on how to fix the memory issues?
#include <iostream>
using std::cout;
using std::endl;
int * doubleSize(int * p, int & cap) {
//create dynamically allocated double size array
int *doubleSize = new int(cap * 2);
//store old array values into new array
for (int i = 0; i < cap; i++) {
doubleSize[i] = p[i];
}
cap = cap * 2;
delete[] p; //deallocate old memory
return doubleSize;
}
int main() {
int cap = 3;
int *p = new int(cap);
//initialize an array
for (int i = 0; i < cap; i++) {
p[i] = i;
}
int *s = doubleSize(p, cap);
for (int i = 0; i < 6; i++) {
cout << s[i] << endl;
}
//deallocate memory
delete p;
delete s;
}
Several problems in the code:
int *p = new int(cap);
and
int *doubleSize = new int(cap * 2);
both allocate a single int with the value cap or cap * 2
Since arrays of int are expected by the rest of the code, these need to be corrected to
int *p = new int[cap];
and
int *doubleSize = new int[cap * 2];
Then
delete p;
delete s;
must be changed to
delete[] p;
delete[] s;
in order to correctly delete arrays.
But!
delete[] p;
already happened back in doubleSize when the array was replaced. It could be removed, but the code would be cleaner with
p = doubleSize(p, cap);
and the variable s being removed instead.

Solving Segmentation Fault(core dumping) error

This program doubles the every second integer for the account number given and if the number is greater than 10 it is subtracted by 9. Then output whether the number entered is correct or not. Assuming that the account number is off 5 numbers. I wrote this program but does not get the answer for few number but got a correct answer for other number. Thanks for hint.
#include <iostream>
class AccountNumber {
private:
int size = 5;
int *p;
public:
AccountNumber() { int *p = new (std::nothrow) int[size]; }
~AccountNumber() { delete[] p; }
void getaccount() {
int acc;
std::cout << "Enter the account number: ";
std::cin >> acc;
for (int i = 0; i < size; i++) {
p[i] = acc % 10;
}
setaccount(p);
}
void setaccount(int a[]) {
for (int i = 0; i < size; i++) {
p[i] = a[i];
}
}
void doubles() {
AccountNumber at;
at.p = new int[size];
at.p = p;
for (int i = 0; i < size; i++) {
if (i % 2 == 1) {
at.p[i] = at.p[i] * 2;
if (at.p[i] > 10) {
at.p[i] = at.p[i] - 9;
}
}
}
p = at.p;
}
bool sum() {
bool ot;
int sum = 0;
for (int i = 0; i < size; i++) {
sum = sum + p[i];
}
int mod = sum % 10;
if (mod == 0) {
ot = true;
} else {
ot = false;
}
return ot;
}
void display(std::ostream &outs) {
bool ot = sum();
doubles();
outs << "Account number entered is ";
if (ot) {
outs << " correct.\n";
} else {
outs << " is not correct. \n";
}
}
};
int main(int argc, char const *argv[]) {
AccountNumber accn;
accn.getaccount();
accn.display(std::cout);
return 0;
}
Output
Enter the account number: 35556
Segmentation fault (core dumped)
I don't know where I'm going wrong.
The issue here is that you never allocate p. Look at your constructor:
AccountNumber()
{
int *p = new(std::nothrow) int[size];
}
Here you are defining a new pointer variable p, which will be used instead of the member pointer variable p you defined in the private fields. What happens here is that you are allocating an int array for a new variable p, but that variable p gets thrown out at the end of the constructor (and also causes a memory leak because of the dynamic allocation that will never be reclaimed).
What you should do here instead is simply assigning the new allocated array to the member pointer variable p without redefining it, ie.
AccountNumber() {
p = new (std::nothrow) int[size];
}
And to prevent such mistakes from happening again, you should consider using a specific naming convention for class members, such as m_ prefix (for example)
class AccountNumber {
private:
int m_size = 5;
int *m_p;
public:
AccountNumber() {
m_p = new (std::nothrow) int[size];
}
};

How to delete completely 2D pointer array

I have a 2D pointer matrix in C++ such as,
typedef unsigned char U8;
typedef unsigned int U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
A[i] = new U8[m_L];
}
After setting value in A0, I will write a function which decide delete or not delete M-2 rows in A, depends on the random number is 0 or 1
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
}
}
}
Now, in main function (which contains A memory allocation), I want to free/delete the memory which allocated for A. I can use the code
//free A matrix
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
delete[] A;
A = NULL;
My problem is that, I don't know that A is delete (M-2) rows or not. Hence, above code does clearly delete all memory, if my random number is 0. That means, above code only delete correct memory if M-2 rows is deleted in the delete_or_not function. How can delete the A matrix perfectly. Thanks
Finaly, my full code is
typedef unsigned char U8;
typedef unsigned int U32;
int M=10;
int m_L=8;
U8** A = new U8*[M];
for (U32 i = 0; i < M; ++i)
{
A[i] = new U8[m_L];
}
delete_or_not(A,M);
//free A matrix
//Way 1: will miss M-2 row if delete_or_not function did not delete 2 rows.
// It only correct if rand_num=1
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
delete[] A;
A = NULL;
//Way 2- It will correct if the size of A is M by M
for (U32 i = 0; i < M; ++i)
{
delete[] A[i];
A[i] = NULL;
}
delete[] A;
A = NULL;
Just set deleted elements to NULL and everything will work fine:
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
A[index] = NULL;
}
}
}
Also, this is not very useful:
for (U32 i = 0; i < M; ++i)
{
if (i < m_L)
{
delete[] A[i];
A[i] = NULL;
}
}
There's no point advancing i from 0 to M if you then only "do work" when i is smaller then m_L.
But really, in C++ you should probably use std::vector<std::vector<U8>> instead and simply erase or pop_back to get rid of "rows".
In void delete_or_notyou shall set deleted elements to NULL as already proposed by another answer by Amit.
Then Way 2 of your posted code is correct in both cases.
Calling delete on a NULL is perfectly legal and doesn't hurt at all.
Way 1 is not working and should be removed.
In summary:
void delete_or_not(U8** A,int M)
{
if (rand_num==1){
for (U32 index = M-2; index < M; ++index){
delete[] A[index];
A[index] = NULL; // Add this to your code
}
}
}
// In main somewhere...
// free A
for (U32 i = 0; i < M; ++i)
{
delete[] A[i]; // Not a problem if the element has already been deleted
// because the pointer will be NULL and calling
// delete with NULL is OK (and changes nothing)
A[i] = NULL;
}
delete[] A;
A = NULL;

Memory Management with delete

I have a little program:
#include <iostream>
using namespace std;
void inputArray(int*& p, int& n);
void print(int *p, int n);
int main() {
int size = 0;
int *arr;
inputArray(arr, size);
}
void inputArray(int*& p, int& n) {
int *q = new int[n]; int m = n;
for (int i = 0; i < n; ++i) q[i] = p[i];
cout << endl << "How many numbers to insert? "; cin >> n;
delete p;
p = new int[n + m];
for (int i = 0; i < m; ++i) p[i] = q[i];
for (int i = 0; i < n; ++i) cin >> p[i + m];
n += m;
}
The purpose of this program is to insert an array of integer. However, when I try to run the program with Code::Blocks on Ubuntu, it often says:
free(): invalid pointer: 0xb7646000 ***
after I input n.
However, when I remove delete p; , everything works well. However, I still want to know the problem. Can anyone tell what the problem is?
delete p;
You never allocated p, so when you try to free p, it can't.
It's like trying to access someone else's bank account, you may have the name, but you ain't allowed to free his money.
And - just for the rant- , try using more verbose variable names, it never hurts. Especially if you drunk-review your code in a year.
You are assigning elements from the array p
for (int i = 0; i < n; ++i) q[i] = p[i];
But p was never allocated or assigned any values
int *arr;
inputArray(arr, size); // Here "arr" is "p" within the function
This constitutes undefined behavior and will behave as such.

Error deleting pointer of arrays pointing to arrays C++

I am currently creating a program that simulates a Galton board in C++. I understand how to create a pointer, create an array of pointers, and point each one at another array of ints. My problem is occuring when i try to descruct my pointer array, its telling me:
"Debug Error!
HEAP CORRUPTION DETECTED: after Normal block (#927) at 0x0115E978.
CRT detected that the application wrote to memory after end of heap buffer."
I've been banging my head against the wall with this one, as it seems all the examples I can find online have this exact approach. I even rewrote my program into a class to make it more simple. The program runs and does exactly what it's supposed to until the ob1 starts to descruct, which is when the program pukes. I'm stuck.
Here is my code:
#include <iostream>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
class foo
{
public:
foo();
foo(int);
~foo();
void allocateSpace();
void runGame();
void printResults();
private:
int bins;
int** p;
};
foo::foo()
{
this->bins = 0;
}
foo::foo(int bins)
{
this->bins = bins;
this->p = new int*[bins]; //setting p to array of pointers
}
foo::~foo()
{
for (int i = 0; i < bins; i++)
{
delete[] this->p[i];
}
delete[] p;
}
void foo::allocateSpace()
{
for (int i = 0; i < bins; i++)
{
this->p[i] = new int[i]; //creatung an int array of size i at each pointer array cell
for (int j = 0; j <= i; j++)
{
this->p[i][j] = 0;
}
}
}
void foo::runGame()
{
const int numOfRuns = 1000;
for (int i = 0; i < numOfRuns; i++)
{
this->p[0][0]++; //each ball hits the first peg, so always increment it before anything else
int j = 0; //setting j = 0 sets it to the left
for (int i = 1; i < bins; i++)
{
int rando = rand() % 2;
if (rando == 1) //move right
{
j++;
}
this->p[i][j]++;
}
}
}
void foo::printResults()
{
for (int i = 0; i < bins; i++)
{
for (int j = 0; j <= i; j++)
{
cout << setw(5) << this->p[i][j];
}
cout << endl;
}
}
int main()
{
srand(time(0));
int numOfBins;
cout << "Enter the number of bins: ";
cin >> numOfBins;
cout << endl;
foo ob1(numOfBins);
for (int i = 0; i < 50; i++)
{
ob1.allocateSpace();
ob1.runGame();
ob1.printResults();
}
system("pause");
return 0;
}
Any help would be much appreciated.
In allocateSpace, you write beyond the allocated object. This corrupts your heap.
this->p[i] = new int[i];
for (int j = 0; j <= i; j++)
{
this->p[i][j] = 0;
}
printResults has a similar problem: You read beyond the allocated object.
Then, in runGame, you attempt to increment a 0 sized object.
this->p[0][0]++;
The fix:
It seems you need to increase your allocation by 1.
this->p[i] = new int[i+1];
This will avoid the heap corruption issue. You still have a memory leak issue, because you allocate new memory on top of your existing memory on each iteration in main().
Your code would be safer if you adopted the use of vector<> instead of managing dynamically allocated arrays.