Segmentation fault from accessing 2d array passed to a function - c++

I am using Code:Block.
Compiled the following code(no errors) and while running got segmentation fault.
void print(int size, int **a)
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";/**Segmentation fault here**/
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,(int **)a);
return 0;
}
I tried using different methods of passing the array:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int size = sizeof(a)/sizeof(a[0]);
print(size,a);
return 0;
}
I got no error, code ran successfully.
For the first code instead of using a[i][j], I tried with *(*(a+i)+j), got segmentation fault.
Then I debugged the first code at the point of segmentation fault and absorbed the following:
> p a
$1 = (int **) 0x22fd30
> p *a
$2 = (int *) 0x200000001
> p **a
Cannot access memory at address 0x200000001
I believe that a hold the first address of the 2d array. but for p **a there is a different address shown in the error message.
Then I ran the first code in http://ideone.com/ and encountered run time error. Where am I making mistake? and why the debugger showing different address?.

In your first example
void print(int size, int **a)
expects second argument of type pointer to pointer to int. But here
int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
print(size,(int **)a);
you pass a variable of type array of 4 arrays of 4 ints. When you pass an array to function, array decays to pointer to its first element. So actually function print gets argument of type int *[4] - pointer to array of 4 ints which is not what print expects. That's an error. You hide this error from compiler telling him that a has type int **. It doesn't. Hence the segmentation fault.
In your second example
void print(int size, int a[][4])
expects an argument of type array of arrays of 4 ints. It decays to int *[4] which is exactly the type of a when it decays while passed to print function. No error here.

If you index an int**, in your case a[0] for example, the resulting type is int*. If you index that again, as in a[0][0], it will interpret the first element (being the integer 1) (or first two elements on 64-bit) as a pointer to int (int*) and attempt to dereference it, which is obviously incorrect and will usually lead to a segmentation fault.
Your C-style cast (int**) is translated to a reinterpret_cast. Which is why I don't like C-style casts as it's not always obvious what they do.
In short: with your cast to (int**) you're telling the compiler that it's an array of pointers to int, which it isn't: it's an array of int[4]'s.
Edit: my comment about 64-bit only holds for platforms where sizeof(int) is always 4. I believe on linux sizeof(int) == sizeof(int*).

Replace cout<<a[i][j]<<" "; with cout<<a[i*size+j]<<" ";

Problem you are facing is because of Data type of both is different. int arr[][] is different from int ** arr. Lets see from 1-d array when you declare int arr[], arr it is same as int *arr. When you try to access it arr[i] internally what compiler does *(arr+i). But when you declare int arr[][size] data type of arr is int (*arr)[size] which is different from int **arr. That's why you get error. see this Link

The following works for me:
Allocation and assignment:
int** foo( int N, int M)
{
int** arr;
arr = (int **)malloc(sizeof(int *)*N);
for(int i=0; i < N; i++) {
arr[i] = (int *)malloc(sizeof(int)*M);
}
int x=0;
for(int i=0;i<N;i++)
{
for(int j=0;j<M;j++)
{
arr[i][j]=x;
x++;
}
}
return arr;
}
Now you can use it like this:
void print(int size, int a[][4])
{
for(int i=0;i<size;i++)
{
for(int j=0;j<size;j++)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int main()
{
int N=2;
int M=3;
int** foo = bar(N,M);
print(arr,N,M);
}

Related

C++ malloc(): corrupted top size on loop

I'm trying to create a function printarr that prints a dynamically sized array. However, whenever I try to run the code I get the error above. I tried copying code I found online as well, but get the same error, so I'm wondering if there's something wrong with my installation, or another part of the code is somehow affecting it. The entire thing seems super simple, which makes me even more stumped. Here's the code:
#include <iostream>
using namespace std;
//Generates an array with k inversions of size n
int* generate_k_inversion(int k, int n){
int *arr=new int(n);
//Check if number of inversions is possible
if(k>(n*(n-1)/2)){
cout<<"Impossible number of inversions!";
throw(-1);
}
//Loop to generate points
for(int i=0;i < n;i++){
arr[i]=i;
}
//Loop to invert
return arr;
}
//Copies dynamic arrays of size n
int* copy(int* arr1,int n){
int* arr2=new int(n);
for(int i=0;i<n;i++){
arr2[i]=arr1[i];
}
return(arr2);
}
//Generates output of best and worst cases of bubble and insertion sort in integers of size n
void test1(int n){
//generate best case
int *arrb1=generate_k_inversion(0,n);
int *arrb2=copy(arrb2,n);
delete [] arrb1;
delete [] arrb2;
//generate worst case
int *arrw1=generate_k_inversion((n*(n-1)/2),n);
int *arrw2=copy(arrw2,n);
delete [] arrw1;
delete [] arrw2;
}
//Prints a dynamic array arr of size n
void printarr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
}
//Just initialize both tests
int main(){
int size=10;
int* arr1=generate_k_inversion(0,size);
printarr(arr1,size);
delete [] arr1;
}
Thanks for the help
The line
int *arr=new int(n);
will allocate memory for a single int and initialize that int to n.
Therefore, the loop
for(int i=0;i < n;i++){
arr[i]=i;
}
will access arr out of bounds, causing undefined behavior.
What you probably want is to write
int *arr=new int[n];
instead, which will allocate memory for n values of type int.

returning an array address from function in c++ issue

i'm new to programming , this code gives me syntax error in line => int *result = apply_all(array1,5,array2,3) this is the error: expected primary-expression before '}' token|
i'm trying to write function called apply_all expects 2 arrays of integers and their sizes and dynamically allocates a new array of integers whose size is the product of 2 array sizes.
the function should loop through the 2nd array and multiple each element accross each element of array 1 and store the product in newly created array. the function is returning a pointer of to the newly allocated array.
also i wrote a function which is print to display the 1st & 2nd & newly array.
#include <iostream>
using namespace std;
//function prototype
int *apply_all(int *array1 ,int size1,int *array2,int size2);
void print(int *array,int size);
int main()
{
int array1[] {1,2,3,4,5};
int array2[] {10,20,30};
cout << "Array 1:";
print(array1,5);
cout << "Array 2:";
print(array2,3);
int *result = apply_all(array1,5,array2,3);
cout << "Result : ";
print(result,15);
delete [] result;
return 0;
}
int *apply_all(int *array1 ,int size1,int *array2,int size2)
{
int *result {nullptr};
result = new int[size1 * size2];
for (int i{0};i<size2;i++)
for(int j{0};j<size1;j++)
*(result[i*5+j]) = *(array1[i])**(array2[j]);
return result;
}
void print(int *array,int size)
{
for(auto num:array)
cout << num << endl;
}
On this line:
*(result[i*5+j]) = *(array1[i])**(array2[j]);
since result[i*5+j] gives you an int, you are trying to dereference an int, which is not possible.
You just need to do:
result[i*5+j] = array1[i] * array2[j];
Also, in print, your range-for loop won't work with a pointer. You need to do:
for(int i = 0; i < size; ++i)
cout << array[i] << endl;
Also, in apply_all, your loop bounds are incorrect. i needs to go till size1, and j needs to go to size2.
Here's a demo.
Since you are new, a simple work around would be creating an array with buffer space to store your results in and passing the pointer for this into apply_all. You could then write to this array which (being declared in main) should be very easy to access and cause few errors and use a c-string like ending to know when your results are over and to stop printing from the array (c-strings end with a value of 0 so that programs don't read unrelated memory). eg:
int buf[99];
apply_all(array_1, size1, array_2, size2, buf, size3);
for (int x = 0; buf[x] != end of buf var; x++;)
{
print(buf[x])
}
and
apply_all()
{
buf[start-end] = whatever you want;
buf[end + 1] = some variable that won't appear in buffer; //max int size?
}

Function which uses array of pointers

I have got this question on my c++ homework.
Write and test the function location that takes, as shown below, a
table of pointers to integers p, the size of such a table n and an
integer value x.
int* location (int* p [ ], int n, int x);
location searches the set of integers pointed at by the table of
pointers p for a match to the value of x. If a matching integer is
found, then location returns the address of that integer, NULL
otherwise.
I'm not sure that I fully understand the question. However, I tried to solve it but I got error(the program crashes). Here is my code.
#include<iostream>
using namespace std;
int* location (int* p [ ], int n, int x);
void main(){
int arr[3]={1,2,3};
int *ptr=arr;
int *address= location (&ptr, 3, 2);
cout<<&arr[3]<<" should be equal to "<<address<<endl;
}
int* location (int* p [ ], int n, int x){
for(int i=0; i<n; i++){
if(*p[i]==x){return p[i];}
}
return NULL;
}
Can someone please show me my mistake or tell me if I'm solving the question correctly?
Thanks
This is not correct in your code:
cout<<&arr[3]<<" should be equal to "<<address<<endl;
You are accessing array element with index 3, however, maximum index you can access in your case is 2. Also, there is alternative solution below.
Also the way you are passing pointer to a pointer to your location function (and also using it) is wrong. Because for example you haven't declared array of pointers to integers in the first place.
You can try to read somewhere a bit more on the notion of array of pointers in C++, in order to better understand the example below.
#include <iostream>
using namespace std;
const int MAX = 3;
int* location (int* p [ ], int n, int x);
int main ()
{
int var[MAX] = {10, 100, 200};
// Declare array of pointers to integers
int *ptr[MAX];
for (int i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; // Store addresses of integers
}
int *x = location(ptr, MAX, 100); // Now you have pointer to the integer you were looking for, you can print its value for example
if(x != NULL) cout<<*x;
return 0;
}
int* location (int* p [ ], int n, int x)
{
for(int i = 0; i<n; i++)
{
if(*p[i] == x) return p[i];
}
return NULL;
}

passing modified array values back to main function in C++

Write a reverse function that takes an integer array and its length as arguments. Your
function should reverse the contents of the array, leaving the reversed values in the original
array, and return nothing.
#include<iostream>
using namespace std;
void printArray(int a[], const int n)
{
for(int i=0;i<n;i++)
{
cout<<a[i];
i!=n-1 ? cout<<", " : cout<<"";
}
}
void reverse(int a[], const int n)
{
int reverse[n];
for(int i=0;i<n;i++)
{
reverse[n-1-i]=a[i];
}
a = reverse;
}
int main()
{
int *a,n;
cin>>n;
a = new int[n];
for(int i=0;i<n;i++)
a[i]=0;
a[0]=1;
reverse(a,n);
printArray(a,n);
delete [] a;
a = NULL;
return 0;
}
After calling reverse function the array from main is not modifying, please advice! :(
You can't assign one array to another. Instead copy from reverse to back into a:
std::copy(reverse, reverse + n, a);
Or possibly
memcpy(a, reverse, n * sizeof(int));
You are not copying the data from reverse back to a - you are instead pointing it (a) to a memory location that will no longer exist (be valid) after your function returns. You need to copy the values from reverse back to a. And I would recommend not using the same name for a function and a variable.
Try
void reverse(int a[], const int n)
{
int reverse[n];
for(int i=0;i<n;i++)
{
reverse[n-1-i]=a[i];
}
for(int i=0;i<n;i++)
{
a[i]=reverse[i];
}
}
As was pointed out in comments, the above shows one way of getting the reversed data into array a. It is not the only way - memcpy is considered a more efficient function to use. Even more efficient would be to do in place reversal - this would require a loop of just n/2 iterations while the above loops for 2n and is thus about 4x less efficient.
I recommend that you study all the answers provided - they highlight different aspects of memory handling, code efficiency etc.; something to learn from all of them.
Pointers! They're really useful.
void reverse (int *a, const size_t n)
{
int *b = a + n - 1;
while (b > a)
{
const int swap_value = *a;
*a = *b;
*b = swap_value;
++a;
--b;
}
}
Aha, you know you should pass int a[], a pointer to a, to reverse(), but you still encounter the same problem. You can't modify the pointer stored in a, unless you pass &a to reverse().

Inputing the Size of a 2-dimentional Array

In my code I input the sizes of both dimensions and then declare a two-dimensional array. My question is, how do I use that array as a function parameter? I know that I need to write the number of columns in the function specification but how do I pass the number of columns?
void gameDisplay(gameCell p[][int &col],int a,int b) {
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
if(p[i][j].getStat()==closed)cout<<"C ";
if(p[i][j].getStat()==secure)cout<<"S ";
if(p[i][j].getBomb()==true&&p[i][j].getStat()==open)cout<<"% ";
if(p[i][j].getBomb()==false&&p[i][j].getStat()==open) {
if(p[i][j].getNum()==0)cout<<"0 ";
else cout<<p[i][j].getNum()<<" ";
}
cout<<endl;
}
}
}
int main() {
int row,col,m;
cout<<"Rows: ";cin>>row;cout<<"Columns: ";cin>>col;
m=row*col;
gameCell p[row][col];
gameConstruct(p[][col],m);
gameDisplay(p[][col],row,col);
}
I tried this way but it doesn't work.
Thank you.
In C++, you cannot have variable length arrays. That is, you can't take an input integer and use it as the size of an array, like so:
std::cin >> x;
int array[x];
(This will work in gcc but it is a non-portable extension)
But of course, it is possible to do something similar. The language feature that allows you to have dynamically sized arrays is dynamic allocation with new[]. You can do this:
std::cin >> x;
int* array = new int[x];
But note, array here is not an array type. It is a pointer type. If you want to dynamically allocate a two dimensional array, you have to do something like so:
std::cin >> x >> y;
int** array = new int*[x]; // First allocate an array of pointers
for (int i = 0; i < x; i++) {
array[i] = new int[y]; // Allocate each row of the 2D array
}
But again, this is still not an array type. It is now an int**, or a "pointer to pointer to int". If you want to pass this to a function, you will need the argument of the function to be int**. For example:
void func(int**);
func(array);
That will be fine. However, you almost always need to know the dimensions of the array inside the function. How can you do that? Just pass them as extra arguments!
void func(int**, int, int);
func(array, x, y);
This is of course one way to do it, but it's certainly not the idiomatic C++ way to do it. It has problems with safety, because its very easy to forget to delete everything. You have to manually manage the memory allocation. You will have to do this to avoid a memory leak:
for (int i = 0; i < x; i++) {
delete[] array[i];
}
delete[] array;
So forget everything I just told you. Make use of the standard library containers. You can easily use std::vector and have no concern for passing the dimensions:
void func(std::vector<std::vector<int>>);
std::cin >> x >> y;
std::vector<std::vector<int>> vec(x, std::vector<int>(y));
func(vec);
If you do end up dealing with array types instead of dynamically allocating your arrays, then you can get the dimensions of your array by defining a template function that takes a reference to an array:
template <int N, int M>
void func(int (&array)[N][M]);
The function will be instantiated for all different sizes of array that are passed to it. The template parameters (dimensions of the array) must be known at compile time.
I made a little program:
#include <iostream>
using namespace std;
void fun(int tab[][6], int first)
{}
int main(int argc, char *argv[])
{
int tab[5][6];
fun(tab, 5);
return 0;
}
In function definition you must put size of second index. Number of column is passed as argument.
I'm guessing from Problems with 'int' that you have followed the advices of the validated question and that you are using std::vector
Here is a function that returns the number of columns of an "array" (and 0 if there is a problem).
int num_column(const std::vector<std::vector<int> > & data){
if(data.size() == 0){
std::cout << "There is no row" << std::endl;
return 0;
}
int first_col_size = data[0].size();
for(auto row : data) {
if(row.size() != first_col_size){
std::cout << "All the columns don't have the same size" << std::endl;
return 0;
}
}
return first_col_size;
}
If you're using C-style arrays, you might want to make a reference in the parameter:
int (&array)[2][2]; // reference to 2-dimensional array
is this what you're looking for?
int* generate2DArray(int rowSize, int colSize)
{
int* array2D = new int[rowSize, colSize];
return array2D;
}
example . . .
#include <iostream>
#include <stdio.h>
int* generate2DArray(int rowSize, int colSize);
int random(int min, int max);
int main()
{
using namespace std;
int row, col;
cout << "Enter row, then colums:";
cin >> row >> col;
//fill array and display
int *ptr = generate2DArray(row, col);
for(int i=0; i<row; ++i)
for(int j=0; j<col; ++j)
{
ptr[i,j] = random(-50,50);
printf("[%i][%i]: %i\n", i, j, ptr[i,j]);
}
return 0;
}
int* generate2DArray(int rowSize, int colSize)
{
int* array2D = new int[rowSize, colSize];
return array2D;
}
int random(int min, int max)
{
return (rand() % (max+1)) + min;
}
instead of accessing p[i][j] you should access p[i*b + j] - this is actually what the compiler do for you since int[a][b] is flattened in the memory to an array in size of a*b
Also, you can change the prototype of the function to "void gameDisplay(gameCell p[],int a,int b)"
The fixed code:
void gameDisplay(gameCell p[],int a, int b) {
for(int i=0;i<a;i++) {
for(int j=0;j<b;j++) {
if(p[i*a +j].getStat()==closed)cout<<"C ";
if(p[i*a +j].getStat()==secure)cout<<"S ";
if(p[i*a +j].getBomb()==true&&p[i][j].getStat()==open)cout<<"% ";
if(p[i*a +j].getBomb()==false&&p[i][j].getStat()==open) {
if(p[i*a +j].getNum()==0)cout<<"0 ";
else cout<<p[i*a +j].getNum()<<" ";
}
cout<<endl;
}
}
}
int main() {
int row,col,m;
cout<<"Rows: ";cin>>row;cout<<"Columns: ";cin>>col;
m=row*col;
gameCell p[row][col];
gameConstruct(p[][col],m);
gameDisplay(p[],row,col);
}