Int Matrix com ponteiros em C - Confusão de alocação de memória
-
01-07-2019 - |
Pergunta
Estou tendo alguns problemas com a produção de uma matriz int sem criar vazamentos de memória. Quero poder transformar uma determinada matriz (global) em qualquer tamanho dinamicamente via read_matrix (). Mas então eu quero poder liberar a memória mais tarde. Portanto, no meu método principal, o segundo printf deve resultar em um erro de barramento, pois não deve ter nenhuma memória alocada a ele. Como eu iria criar isso?
int** first_matrix;
int** second_matrix;
int** result_matrix;
int** read_matrix(int size_x, int size_y)
{
int** matrix;
matrix = calloc(size_x, sizeof(int*));
for(int i = 0;i<size_x;i++) {
matrix[i] = calloc(size_y, sizeof(int));
}
for(int i = 0;i<size_x;i++) {
for(int j = 0;j<size_y;j++) {
matrix[i][j] = i*10+j;
}
}
return matrix;
}
int main(int stackc, char** stack)
{
first_matrix = read_matrix(10,10);
printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
free(*first_matrix);
free(first_matrix);
printf("9:3 %d - 4:6 %d \n", first_matrix[9][3], first_matrix[4][6]);
}
Solução
Só porque a memória foi livre não significa que você não pode acessar! Claro, é um muito mal A ideia de acessá -lo depois de ser gratuita, mas é por isso que funciona no seu exemplo.
Observe que free( *first_matrix )
Apenas livre's first_matrix[0]
, não as outras matrizes. Você provavelmente deseja que algum tipo de marcador signifique a última matriz (a menos que você sempre saiba quando libertar a matriz externa quantas matrizes internas você alocou). Algo como:
int** read_matrix(int size_x, int size_y)
{
int** matrix;
matrix = calloc(size_x, 1+sizeof(int*)); // alloc one extra ptr
for(int i = 0;i<size_x;i++) {
matrix[i] = calloc(size_y, sizeof(int));
}
matrix[size_x] = NULL; // set the extra ptr to NULL
for(int i = 0;i<size_x;i++) {
for(int j = 0;j<size_y;j++) {
matrix[i][j] = i*10+j;
}
}
return matrix;
}
Então, quando você está libertando -os:
// keep looping until you find the NULL one
for( int i=0; first_matrix[i] != NULL; i++ ) {
free( first_matrix[i] );
}
free( first_matrix );
Outras dicas
Você precisa liberar cada linha individualmente:
void free_matrix(int **matrix, int size_x)
{
for(int i = 0; i < size_x; i++)
free(matrix[i]);
free(matrix);
}
Liberar a memória não faz com que ela desapareça, apenas significa que outra alocação pode pegar o mesmo pedaço de memória. Tudo o que você colocar nele ainda estará lá até que algo mais o substitua.
Além disso, você não está liberando tudo o que alocou. Você está apenas liberando a variedade de ponteiros e a primeira linha. Mas mesmo se você libertar tudo corretamente, ainda terá o mesmo efeito.
Se você deseja criar um "erro de barramento", precisa apontar para a memória que não pertence ao seu processo. Por que você quer fazer isso de qualquer maneira?
Você só libertou a primeira linha (ou coluna) de First_Matrix. Escreva outra função como esta:
void free_matrix(int **matrix, int rows)
{
int i;
for(i=0; i<rows; i++)
{
free(matrix[i]);
}
free(matrix);
}
Você pode querer transformar a matriz em uma estrutura para armazenar sua contagem de linhas e colunas.
Eu recomendo usar o Valgrind para rastrear a memória não -adquirida, em vez de tentar fazer com que ocorra um erro de barramento. Ele arrasa para muitas outras coisas também.
Sam
Você está recebendo vazamentos de memória porque está liberando a primeira linha da matriz e a lista de linhas, mas nenhuma das linhas 1 a Nth. Você precisa ligar gratuitamente em um loop.
Existem algumas alternativas, no entanto: - alocar tamanho de (int*)linhas + linhascols*sizeof (int) bytes e use os primeiros bytes para os ponteiros da linha. Dessa forma, você só tem um único pedaço de memória para libertar (e também é mais fácil para o alocador) - use uma estrutura que contém o número de linhas. Em seguida, você pode evitar completamente a lista de linhas (salvando memória). A única desvantagem é que você precisa usar uma função, uma macro ou alguma notação confusa para abordar a matriz.
Se você for com a segunda opção, poderá usar uma estrutura como essa em qualquer compilador C99 e novamente só precisar
struct matrix {
int rows;
int data[0];
}
O conceito que você está perdendo aqui é que, para cada calloc, deve haver um livre. e que gratuito deve ser aplicado ao ponteiro transmitido do Calloc.
Eu recomendo que você crie uma função (chamada Delete_Matrix) que usa um loop para libertar todos os ponteiros que você alocou aqui
para (int i = 0; i <size_x; i ++) {matrix [i] = calloc (size_y, sizeof (int)); }
Então, uma vez feito, liberte o ponteiro alocado por isso.
matrix = calloc (size_x, sizeof (int*));
Do jeito que você está fazendo agora,
grátis (*primeiro_matrix); grátis (primeiro_matrix);
Não fará o que você quer fazer.