I am trying to create a merge function for two array structures in c++ but am coming up with a bad access error that I don't know how to solve. The error comes up when I am trying to swap the element in the smaller array into the larger, merged array. The code doesn't even go through a single iteration. All three of i, j, and k remain at 0. Any help would be greatly appreciated! Here is the code:
struct Array
{
int *A;
int size;
int length;
};
void display(Array arr){
for (int i = 0; i < arr.length; i++)
std::cout << arr.A[i] << std::endl;
}
Array merge(Array arr1, Array arr2){
Array arr3;
arr3.length = arr1.length + arr2.length;
arr3.size = arr1.length + arr2.length;
int i = 0, j =0, k =0;
while(i <arr1.length && j < arr2.length){
if (arr1.A[i] < arr2.A[j])
{
arr3.A[k] = arr1.A[i]; //(The error is displayed here: Thread 1: EXC_BAD_ACCESS (code=1, address=0x28))
k++;
i++;
}
else if (arr2.A[j] < arr1.A[i])
{
arr3.A[k] = arr2.A[j];
k++;
j++;
}
}
for (; i< arr1.length; i++)
{
arr3.A[k]=arr1.A[i];
k++;
}
for (; i< arr2.length; j++)
{
arr3.A[k]=arr2.A[j];
k++;
}
return arr3;
}
int main() {
Array arr1;
arr1.size = 10;
arr1.length = 5;
arr1.A = new int[arr1.size];
arr1.A[0]= 2;
arr1.A[1]= 6;
arr1.A[2]= 10;
arr1.A[3]= 15;
arr1.A[4]= 25;
Array arr2;
arr2.size = 10;
arr2.length = 5;
arr2.A = new int[arr2.size];
arr2.A[0]= 3;
arr2.A[1]= 4;
arr2.A[2]= 7;
arr2.A[3]= 18;
arr2.A[4]= 20;
Array arr3 = merge(arr1, arr2);
display(arr3);
return 0;
}
Your Array arr3 does not allocate any memory for its int *A field. It's natural that it would not work.
Anyway, your implementation of Array is very poor. Don't reimplement arrays unless you have a good reason; use std::vector instead.
If you really need to implement an Array on your own, then learn about encapsulation, make a class with a constructor, and allocate/delete your data (*A) field properly. Remember, using pointers and heap memory without understanding them is a recipe for disaster.
Easy: arr3.A is not initialized. It's a pointer. What does it point to?
Suggestion: learn about dynamic memory allocation.
Related
I am currently learning how to utilize raw pointers in C++. I understand how to dynamically allocate a 2D array, however, as an exercise for myself, I attempted to apply my understanding of multiple levels of indirection to allocate a 3D array. My attempt is presented below:
int main() {
double*** matrix { new double**[10] {} };
for (size_t i {}; i < 10; ++i) {
matrix[i] = new double*[i + 1] {};
for(size_t j {}; j < 10; ++j) {
matrix[i][j] = new double[i + 1] {};
}
}
std::cout << matrix[0][0][0] << std::endl;
for (size_t i {}; i < 10; ++i) {
for (size_t j {}; j < 10; ++j) {
delete[] matrix[i][j];
matrix[i][j] = nullptr;
}
delete[] matrix[i];
matrix[i] = nullptr;
}
delete[] matrix;
matrix = nullptr;
return 0;
}
Since I'm using uniform initialization, matrix[0][0][0] should print the value 0.0; However, I'm getting a garbage value when doing so. Furthermore, I have a double free or corruption (out) error, which I assume is telling me that I am attempting to free memory from the same address twice.
Any help or guidance would be appreciated. I'm just trying to fully understand raw pointers.
Edit: I understand that double*** is not actually a 3D array. I'm just trying to utilize simple terminology.
matrix[i] = new double*[i + 1] {};
for(size_t j {}; j < 10; ++j) {
This is your error right here, you allocate an array of 'i + 1' element and then loop for 10, you either need to have i + 1 in both places or 10 otherwise this is undefined behavior. The same applies for deletion (the loop checks for 10 but you only allocated i + 1).
I'm writing a simple program within which a dynamic array is to be created. The function that is being used to create said array is in a second .cpp file, attached as a user-made library. Unfortunatelly Visual Studio pops an error saying that the program can't use uninitialized variable. I feel like it's a really easy problem to solve, but I don't know how to get through it. Here is the code:
int main()
{
int i = 5, j = 6;
string** Array;
createDefStruct(Array, i, j);
/*for (int k = 0; k < i; k++)
{
for (int m = 0; m < j; m++)
{
Array[i][j] = "YIKES";
cout << Array[i][j] << '\t';
}
cout << endl;
}*/
deleteDefStruct(Array, i);
return 0;
}
The createDefStruct function:
void createDefStruct(string** Arr, int varAttribCount, int varCount)
{
Arr = new string * [varAttribCount+1];
for (int i = 0; i < varAttribCount+1; i++)
Arr[i] = new string[varCount];
}
How do I go about initilizing a variable?
Thank you in advance!
So the problem is that instead of returning your array from the function you passed the array into the function as parameter. This mean that the variable is uninitialised in main (even though it is initiialised in createDefStruct). Rewrite like this
string** createDefStruct(int varAttribCount, int varCount)
{
string** Arr = new string * [varAttribCount+1];
for (int i = 0; i < varAttribCount+1; i++)
Arr[i] = new string[varCount];
return Arr;
}
int main()
{
int i = 5, j = 6;
string** Array = createDefStruct(i, j);
...
In general when you want a function to return a value you use return from inside the function to return that value. When you want to pass a value into a function you use a parameter. In your createDefStruct function varAttribCount and varCount are the parameters but the array should be a return value.
I'm attempting to teach myself the basics of algorithms and data structures through a free online course, and as such, I though it'd give it a first shot at merge sort. This isn't really going to be used for anything so it's pretty sloppy, but I seem to be having a problem where main is not calling the MergeSort function.
The output is 00000000, (I assume because array is never assigned anything). When I run the program through gdb the program seems to get to that line, and then completely skip over the function and go directly to the loop that prints the array.
Any thoughts? Am I missing something stupid?
#include <iostream>
using namespace std;
int *MergeSort(int array[], int sizeOf);
int main(){
int numbers[8] = {5, 4, 1, 8, 7, 2, 6, 3};
int *array = MergeSort(numbers, 8);
for (int i = 0; i < 8; i++)
cout << array[i];
return 0;
}
int *MergeSort(int array[], int sizeOf){
int *leftArr = new int[sizeOf/2]; // Build arrays to split in half
int *rightArr = new int[sizeOf/2];
if (sizeOf < 2){ // Base case to end recursion
return array;
}
else{
for (int i = 0; i < (sizeOf/2); i++){ // Left gets first half
leftArr[i] = array[i];
}
int j = (sizeOf/2) - 1; // Set point to start building 2nd
for (int i = sizeOf; i >= (sizeOf/2); i--){
rightArr[j] = array[i]; // Build other half of array
j--;
}
leftArr = MergeSort(leftArr, sizeOf/2); // Call Recursive functions
rightArr = MergeSort(rightArr, sizeOf/2);
}
static int *newArray = new int[sizeOf]; // Sorted array to Build
int k = 0; // Iterators to build sorted func
int m = 0;
int p = 0;
while (p < sizeOf){
if (leftArr[k] < rightArr[m]){ // Left Arr's current value is less
newArray[p] = leftArr[k]; // right arr's current calue
k++;
}
else if (leftArr[k] >= rightArr[m]){
newArray[p] = rightArr[k];
m++;
}
p++;
}
//for (int i = 0; i < 8; i++)
// cout << newArray[i] << endl;
return newArray; // Return address to new array
}
There is a fundamental design issue in your MergeSort():
your algorithm is recursive (that's perfect)
unfortunately it returns newArraywhich is static. This means that all invocations use the same instance of the same static variable (and overwrite the one returned by the recursive call).
You need to solve this by making newArray non static. And at the end of the function, you need to delete[] the arrays returned by recursive calls in order to avoid memory leakage.
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &
How would I go about dynamically allocating a multi-dimensional array?
If you know the size of nested dimensions already, you can also literally allocate a multi dimensional array using new:
typedef int dimensions[3][4];
dimensions * dim = new dimensions[10];
dim[/* from 0 to 9 */][/* from 0 to 2 */][/* from 0 to 3 */] = 42;
delete [] dim;
instead of 10, a runtime determined value can be passed. Since it's not part of the type operator new returns, that's allowed. This is nice if you know the number of columns, but want to keep the number of rows variable, for example. The typedef makes it easier to read the code.
For the sake of completeness, here is a better way to do it in C++ when you know the array bounds ahead of time. The benefit of using the following class is that you don't have to care about calling delete[] on your data. This means that this class will be exception-safe, and all of the other great stuff about RAII.
template<typename T, int width, int height>
class MultiArray
{
private:
typedef T cols[height];
cols * data;
public:
T& operator() (int x, int y) { return data[x][y]; }
MultiArray() { data = new cols[width]; }
~MultiArray() { delete [] data; }
};
Usage:
MultiArray<int, 10, 10> myArray;
myArray(2, 3) = 4;
cout << myArray(2, 3);
edit: and, while I'm at it, here is the setup you can use if you don't know the array bounds until runtime:
template<typename T>
class Array2D
{
private:
const int width;
T * data;
public:
T& operator() (int x, int y) { return data[y*width + x]; }
Array2D(const int w, const int h) : width(w) { data = new T[w*h]; }
~Array2D() { delete [] data; }
};
Usage:
Array2D myArray(10, 10);
myArray(3, 4) = 42;
cout << myArray(3, 4);
How about using Boost.Multiarray ? I believe it answers your need quite well !
http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html#sec_introduction
Here is an excerpt from the documentation page :
#include < boost/multi_array.hpp >
#include < cassert >
int main ()
{
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array< double, 3 > array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
// Verify values
int verify = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
assert(A[i][j][k] == verify++);
return 0;
}
See this:
C++ FAQ by Marshall Cline
See "How do I allocate multidimensional arrays using new?" and "But the previous FAQ’s code is SOOOO tricky and error prone! Isn’t there a simpler way?" sections.
std::vector<std::vector<int> >should be mentioned, as it's often the simplest way. However, be aware that it is non-rectangular. Not every std::vector<int> needs to have the same length.
I'm surprised no one has mentioned boost::multi_array yet. I needed a 2D array in a program just last week, and found it to be a lot easier, and quicker to code, than the home-brewed solutions that I've come up with before (all of which are mentioned in other comments).
Here's the implementation I've got; I declare a single contiguous block of ints instead of creating new blocks inside my for loop, so I'm not causing page faults all over the place. Thanks to eJames for pointing out why this code was broken originally.
int width = 10, height = 10, totalSize = width*height;
int **myArray = new int*[width];
int *data = new int[totalSize];
for ( int i = 0; i < height; ++i )
{
myArray[i] = data + (i*width);
}
// do some things here
delete[] data;
delete[] myArray;
Your loop would not write the pointer values into myArray properly. I would suggest the following instead:
int width = 10;
int height = 10;
int ** myArray = new int*[width];
int * data = new int[width*height];
int * index = data;
for (int i = 0; i < width; i++)
{
myArray[i] = index;
index += height;
}
// ...
delete[] data;
delete[] myArray;
As another alternative, STLSoft includes a fixed_array_2d class (as well as 3D and 4D versions). Compared with the homebrewed solutions given here, it has a similar implementation but a more complete feature set (full support for iterators, etc.). Compared with boost::multi_array, it's lighter weight and easier on not-quite-compliant C++ compilers but (intentionally) lacks some of multi_array's features.
You can index a one dimensional as a 2, 3, or N dimensional one if you just space over the correct amount of elements. For example, if I've got 10 rows and 10 columns, I know that if I'm on row 3 I will have to go over at least 30 elements to get to it.
Somehow I prefer this notation for simple 2D arrays since I don't need to worry about nested levels of pointers. The downside is the messier index notation. Here's an example with a 2D array with n rows and m columns:
int *matrix = new int[n*m];
//set element (3,7) to 10
matrix[3*m+7] = 10;
//print the matrix
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << matrix[i*m+j] << ' ';
}
cout << '\n';
}
This a reproduction of a post on another thread. It does exactly what you want, without needing to know the array dimensions ahead of time, and without using boost or STL.
Heres a routine which allocates the 3D array of dimension N1 x N2 x N3 in contiguous memory space while allowing you the a[i][j][k] syntax for operator access. The array is dynamic but continuous so it's a huge plus over the vector<> approach and loops of new[] calls.
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for( i = 0; i < N1; i++) {
if (i < N1 -1 ) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for( j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
And later in your implementation routine...
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
//equivalently, a 'flat' array could be obtained with
//int * array = array3d[0][0];
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
//or if you're using the flat array:
//array[i*N2*N3 + j*N3 + k] = elementNumber++;
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
Gives the output:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}