Error Pointer to pointer in c ++!

3

I created a Matrix class, to manipulate an array. In the class declaration I have the following members (public):

class Matrix{
public:
    unsigned char **mat; //ponteiro para ponteiro de uchar
    int nRows; //numero de linhas
    int nCols; //numero de colunas da matriz
    Matrix(int nRows, int nCols); //construtor
    void putColumn(int *Col, int j); //metodo para adicionar colunas à matriz
}

In the constructor I initialize nRows and nCols and allocate memory to mat.

Matrix::Matrix(int rows, int cols)
//Construtor da classe que recebe número de linhas e número de colunas.
{
    nRows = rows;
    nCols = cols;
    mat = (unsigned char**)malloc(nRows*nCols*sizeof(unsigned char));
}

The indexes of the array are arranged along the memory sequentially, as if we had an array, and to access them would be something like:

unsigned char * p; 
p = mat[i] + j*nRows;//onde i = linha e j =coluna

Then I have a method to add columns to the array:

void Matrix::putColumn(int *Col, int j)
{
    unsigned char *p;
    p = *mat + j*nRows;//j é a coluna que pretendo adicionar
    //ou seja, coluna 1, 2, 3, 4 até completar a matriz
    memcpy(p,Col,nCols);
}

In the main function after creating a Matrix object, I add a column to the array:

unsigned char *col;
col = (unsigned char*) malloc(nlinhas*sizeof(unsigned char));

for ( int i = 1; i <= nlinhas; i++){
    col[i] = i;
}
matrix.putColumn(col,0);

The problem here is that when I run this function (main) on the Matrix putColumn method I get the following error: Access violation writing location 0xcdcdcdcd. Thanks if anyone could help me, thank you!

    
asked by anonymous 26.03.2015 / 13:14

1 answer

5

In addition to the potential issues already mentioned in comments, you are using a pointer pointer ( **mat ) to manipulate the data, but it has not been properly initialized. So when you reference *mat the referenced memory area is not valid.

You do not need to use a pointer to pointer, just have a simple pointer to unsigned char (and it's important to use the same data type to avoid problems). C code example, working:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

unsigned char *mat; // Pointeiro simples, e não ponteiro para ponteiro
int nRows;
int nCols;

void putColumn(unsigned char *Col, int j)
{
    unsigned char *p;
    p = mat + j * nRows; // Aritmética de ponteiro, simples
    memcpy(p, Col, nCols);
}

int main(int argc, char* argv[])
{
    // Reproduzindo o seu construtor
    nRows = 10;
    nCols = 10;
    mat = (unsigned char*) malloc(nRows * nCols * sizeof(unsigned char)); // Alocação de ponteiro simples

    // Reproduzindo o seu main
    unsigned char *col;
    int nlinhas = 10; // Apesar da variável chamar "nlinhas", esse valor DEVERIA ser o mesmo definido em nCols!
    col = (unsigned char*) malloc(nlinhas * sizeof(unsigned char));

    for(int lin = 0; lin < 10; lin++)
    {
        for ( int i = 0; i < nlinhas; i++){
            col[i] = 65 + lin; // Para gravar os caracteres ASCII maiúsculos [A, B, C, ...]
        }
        putColumn(col, lin);
    }

    return 0;
}

The result of this example is as follows (the variable was inspected via the watch window of the Visual Studio 2012 debugger, using mat,100 to limit the display of the memory area to 100 bytes):

AsImentionedincomments,althoughyouuseavariablecallednlinhastosetthesizeofthenewcolumn,itshouldbethesameastheclassproperty(nCols).Forifitissmaller(changetointnlinhas=5;intheexamplecode),youwillleaveinvaliddatainmemory:

  

Note: And the invalid data are all the same ( ýýýýý« ) because I   I ran the build in DEBUG. In RELEASE the compiler does not   automatic pre-initialization of memory areas and there will be what   whether it was already in other previous program executions.

As with putColumn you force the copy with nCols , use a value greater than 10 (in this example) will not give problems.

If your intent with the code is to allow the creation of columns with partial data (as in the example, with nlinhas with lower value, equal to 5 ), it is also good practice to zero the total memory each column using memset . This way you prevent a column from improperly maintaining data from a previous update.

Note also that in your original code ( main ) you updated the new column from the index 1 (and arrays and pointers in C / C ++ are indexed from 0 ):

for ( int i = 1; i <= nlinhas; i++){

In addition to not updating the first position of each column, when you were to update the last column the <= there would exceed the limit of the memory area reserved for your program, also causing problems of improper access. >     

26.03.2015 / 15:25