Reputation: 7590
I'm programming A* code and have a weird 'Segmentation Fault' problem trying to access to a int** matrix.
Here the code of an example of matrix. When i try t plot the first cout i obtained a segmentation fault 11.
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int** matriz;
matriz = (int**) malloc(10 * sizeof(int));
// Defino una matriz de 10x12
for (int i=0; i<10; i++)
{
matriz[i] = (int*) malloc(12 * sizeof(int));
for (int j=0; j < 12; j++)
{
if( i == 11 && j == 5)
matriz[i][j] = 13;
else if( i == 10 && j == 7)
matriz[i][j] = 5;
else if( i == 3 && j == 11)
matriz[i][j] = 4;
else
matriz[i][j] = 0;
}
}
// Imprimo valores de prueba para comprobar que todos son accesible y que no encuentro un 'Segmentation Fault'
cout << "Valor en (11, 5) --> " << matriz[11][5] << endl;
cout << "Valor en (10, 7) --> " << matriz[10][7] << endl;
cout << "Valor normal 0 en (4, 4) --> " << matriz[4][4] << endl;
cout << "Valor en (3, 11) --> " << matriz[3][11] << endl;
return 0;
}
Someone could tell what i'm doing wrong. I can't understand why i can plot the value of coordinates for example (4,4) and (3,11) but no those (11, 5) or (10,7) which are nears the boders of the matrix.
Thanks in advance.
Upvotes: 0
Views: 153
Reputation: 24946
First of all you can read Why pointer to pointer and vector of vector is bad for simple matrices. You'll need to enter password "p2pbad" (without "").
This line
cout << "Valor en (11, 5) --> " << matriz[11][5] << endl;
will try to access an element which is not present since your matrix has only 10 rows but you want to get data from row 11 -> segmentation fault. For the same reason the condition
if( i == 11 && j == 5)
does not make sense. i will never be 11, nor will i == 10
in the next condition ever be true since i<10
.
Writing really nice code for universal matrix handling is a huge task but you could probably write a simple/basic, templated matrix class with some effort.
A basic example using std::allocator would be like
template <typename _T>
class basic_matrix
{
public:
typedef basic_matrix<_T> this_type;
typedef ::std::allocator<_T> alloc;
typedef typename alloc::value_type value;
typedef typename alloc::pointer ptr;
typedef typename alloc::const_pointer const_ptr;
typedef typename alloc::reference ref;
typedef typename alloc::const_reference const_ref;
typedef typename alloc::size_type size;
typedef typename alloc::difference_type diff;
typedef _T&& r_ref;
basic_matrix (void)
: _data(nullptr), _x(0U), _y(0U)
{
}
basic_matrix (size const & x, size const & y)
: _data(nullptr), _x(0U), _y(0U)
{
resize(x,y);
}
~basic_matrix (void)
{
if (!empty()) clear();
}
void resize (size const &x, size const &y)
{
if (x == 0 && y == 0)
{
clear();
}
else
{
ptr new_location = _Allocate(x*y);
if (!empty())
{ // old data existent -> copy it
try
{
size const N = min(x, _x), M = min(y, _y);
for (size i=0; i<N; ++i)
{
for (size j=0; j<M; ++j)
{
*(new_location + i*y + j) = *(_data + i*_y + j);
}
}
}
catch (...)
{
_Deallocate(new_location, x*y);
clear();
throw;
}
}
_data = new_location;
_x = x;
_y = y;
}
}
ref operator() (size const &x, size const &y)
{
if (x >= _x || y >= _y) throw std::exception("OUT OF RANGE");
return *(_data + x*_y + y);
}
const_ref operator() (size const &x, size const &y) const
{
if (x >= _x || y >= _y) throw std::exception("OUT OF RANGE");
return *(_data + x*_y + y);
}
bool empty (void) const
{
return (_data == nullptr);
}
void clear (void)
{
_Deallocate(_data, _x*_y);
_data = nullptr;
_x = 0U;
_y = 0U;
}
protected:
ptr _data;
size _x, _y;
alloc _allocator;
ptr _Allocate (size const &num)
{
ptr new_location;
try
{
new_location = _allocator.allocate(num);
}
catch (...)
{
clear();
throw;
}
return new_location;
}
void _Deallocate (ptr location, size const &num)
{
_allocator.deallocate(location, num);
}
};
You will be required to add a copy constructor and an assignment operator and some other stuff ... whatever you want your matrix interface to behave like...
This works using code like this:
int main (void)
{
basic_matrix<int> matriz(10, 12);
// Defino una matriz de 10x12
for (int i=0; i<10; i++)
{
for (int j=0; j < 12; j++)
{
if( i == 9 && j == 7)
matriz(i,j) = 5;
else if( i == 3 && j == 11)
matriz(i,j) = 4;
else
matriz(i,j) = 0;
}
}
cout << "Valor en (10, 7) --> " << matriz(9,7) << endl;
cout << "Valor normal 0 en (4, 4) --> " << matriz(4,4) << endl;
cout << "Valor en (3, 11) --> " << matriz(3,11) << endl;
return 0;
}
It prints:
Valor en (10, 7) --> 5
Valor normal 0 en (4, 4) --> 0
Valor en (3, 11) --> 4
Upvotes: 3
Reputation: 1
If you use C++ (or better yet C++11, e.g. with a recent GCC -4.7 or better- compiler with g++ -std=gnu++11 -Wall
), you could use std::array
(or std::vector
at least).
And you should at least code
matriz = (int**) malloc(10 * sizeof(int*));
if (!matriz) { perror("malloc matriz"); exit(EXIT_FAILURE); };
(on my Linux/Debian/x86-64 machine, sizeof(int)
is 4, but sizeof(int*)
is 8)
because each individual element of matriz
, e.g. matriz[3]
is a pointer.
I would rather suggest using std::array in C++11, and coding
auto matriz = new std::array<std::array<int,12>,10>();
and #include <array>
Upvotes: 2