我正在尝试做一个程序,它能够乘以运算符首选项等矩阵表达式。 我完成了程序并且它可以工作,但是在完成后我在valgrind中遇到了一些错误。很明显,这是因为在指向下一个矩阵的指针附近使用了free()。但我无法弄清楚如何正确地做到这一点。有人可以帮助我,我将非常感激。
这是我的代码
#include <stdio.h>
#include <stdlib.h>
#include "files.h"
struct MatrixObject *matrix;
struct MatrixObject{
size_t rows;
size_t columns;
int *numbers;
struct MatrixObject *pointToNext;
char sign;
};
struct MatrixObject *newMatrixObject (size_t n, size_t m) {
struct MatrixObject *retVal = malloc (sizeof (struct MatrixObject));
if (retVal == NULL)
return NULL;
retVal->numbers = malloc (n * m * sizeof (int*));
if (retVal->numbers == NULL) {
free (retVal);
return NULL;
}
retVal->pointToNext = malloc(sizeof(struct MatrixObject*));
if (retVal->pointToNext == NULL) {
free (retVal);
return NULL;
}
retVal->rows = n;
retVal->columns = m;
return retVal;
}
struct MatrixObject* getMatrixArray(){
struct MatrixObject *object;
int m, n;
if(scanf("%d %d", &n, &m) != 2){
errorHandle();
}
if(n<0 || m<0){
errorHandle();
}
object = newMatrixObject(n, m);
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(fscanf(stdin, "%d", &(object->numbers[(i*m)+j]))!=1){
errorHandle();
}
}
}
char temp;
int res;
while((res=fscanf(stdin, "%c", &temp))!=EOF){
if(res!=1){
errorHandle();
}
if(temp == '*' || temp == '+' || temp == '-'){
object->sign = temp;
object->pointToNext = getMatrixArray();
return object;
}
}
object->sign = 0;
object->pointToNext = 0;
return object;
}
void multiplyMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2){
int newColumns = matrix2->columns;
int newRows = matrix1->rows;
int* newNumbers = malloc(newColumns * newRows * sizeof(*newNumbers));
int counter = 0;
if(matrix1->columns != matrix2->rows){
errorHandle();
}
for(int i = 0;i<newRows;i++){
for(int k = 0;k<newColumns;k++){
int sum = 0;
for(int j = 0;j<matrix1->columns;j++){
sum+= ((matrix1->numbers)[(i*matrix1->columns)+j]) * ((matrix2->numbers)[(j*matrix2->columns)+k]);
}
newNumbers[counter] = sum;
counter++;
}
}
struct MatrixObject mat = *matrix2;
free(matrix2->numbers);
free(matrix2);
matrix1->pointToNext = mat.pointToNext;
matrix1->sign = mat.sign;
free(matrix1->numbers);
matrix1->numbers = newNumbers;
matrix1->columns = newColumns;
matrix1->rows = newRows;
}
void addMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2, char sign){
if(matrix1->columns != matrix2->columns || matrix1->rows != matrix2->rows){
errorHandle();
}
int columns = matrix1->columns;
int rows = matrix2->rows;
int* newNumbers = malloc(rows*columns*sizeof(*newNumbers));
for(int i = 0;i<rows;i++){
for(int j = 0;j<columns;j++){
if(sign == '+'){
newNumbers[i*columns + j] = matrix1->numbers[i*columns + j] + matrix2->numbers[i*columns + j];
}else{
newNumbers[i*columns + j] = matrix1->numbers[i*columns + j] - matrix2->numbers[i*columns + j];
}
}
}
struct MatrixObject mat = *matrix2;
free(matrix2->numbers);
free(matrix2);
matrix1->pointToNext = mat.pointToNext;
matrix1->sign = mat.sign;
free(matrix1->numbers);
matrix1->numbers = newNumbers;
}
int main(int argc, char *argv[])
{
struct MatrixObject *actualMatrix;
matrix = getMatrixArray();
actualMatrix = matrix;
while(actualMatrix->pointToNext != 0){
if(actualMatrix->sign == '*'){
multiplyMatrix(actualMatrix, actualMatrix->pointToNext);
}
else{
actualMatrix = actualMatrix->pointToNext;
}
}
printMatrix(matrix);
actualMatrix = matrix;
while(actualMatrix->pointToNext != 0){
if(actualMatrix->sign == '+' || actualMatrix->sign == '-'){
addMatrix(actualMatrix, actualMatrix->pointToNext, actualMatrix->sign);
}
}
printMatrix(matrix);
return 0;
}
这是我的valgrind的输出:
==30650==
==30650== HEAP SUMMARY:
==30650== in use at exit: 88 bytes in 6 blocks
==30650== total heap usage: 17 allocs, 11 frees, 2,416 bytes allocated
==30650==
==30650== Searching for pointers to 6 not-freed blocks
==30650== Checked 65,936 bytes
==30650==
==30650== 8 bytes in 1 blocks are definitely lost in loss record 1 of 6
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30650== by 0x400C59: newMatrixObject (main.c:32)
==30650== by 0x400D0F: getMatrixArray (main.c:54)
==30650== by 0x40133F: main (main.c:177)
==30650==
==30650== 8 bytes in 1 blocks are definitely lost in loss record 2 of 6
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30650== by 0x400C59: newMatrixObject (main.c:32)
==30650== by 0x400D0F: getMatrixArray (main.c:54)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x40133F: main (main.c:177)
==30650==
==30650== 8 bytes in 1 blocks are definitely lost in loss record 3 of 6
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30650== by 0x400C59: newMatrixObject (main.c:32)
==30650== by 0x400D0F: getMatrixArray (main.c:54)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x40133F: main (main.c:177)
==30650==
==30650== 8 bytes in 1 blocks are definitely lost in loss record 4 of 6
==30650== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30650== by 0x400C59: newMatrixObject (main.c:32)
==30650== by 0x400D0F: getMatrixArray (main.c:54)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x400DC3: getMatrixArray (main.c:71)
==30650== by 0x40133F: main (main.c:177)
==30650==
==30650== LEAK SUMMARY:
==30650== definitely lost: 32 bytes in 4 blocks
==30650== indirectly lost: 0 bytes in 0 blocks
==30650== possibly lost: 0 bytes in 0 blocks
==30650== still reachable: 56 bytes in 2 blocks
==30650== suppressed: 0 bytes in 0 blocks
==30650== Reachable blocks (those to which a pointer was found) are not shown.
==30650== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==30650==
==30650== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
以下是数字行的一些信息:
32: retVal->pointToNext = malloc(sizeof(struct MatrixObject*));
54: object = newMatrixObject(n, m);
71: object->pointToNext = getMatrixArray();
177:matrix = getMatrixArray();
答案 0 :(得分:0)
我看到的第一个是
struct MtrixObject *newMatrixObject (size_t n, size_t m) {
//...
retVal->pointToNext = malloc(sizeof(struct MatrixObject*));
if (retVal->pointToNext == NULL) {
free (retVal);
return NULL;
}
retVal的编号在错误检查块中永远不会自由。请记住,释放结构不会释放由malloc
初始化的任何变量在你的主体中,矩阵或者realMatrix不是免费的。 看起来你正在创建一个默认矩阵,actualMatrix,然后编辑它然后设置一个指针pointToNext来指向编辑过的矩阵。之后,您将actualMatrix设置回默认矩阵。 (这是我在这里看到的LinkedList吗?)
这意味着你有一系列基础不自由的matricies。你应该尝试
struct MatrixObject *temp;
while (matrix != NULL) {
temp = matrix.pointToNext;
free(matrix);
matrix = temp;
}
这将遍历第一个矩阵之后的所有矩阵并释放它们。
请注意,我不知道printMatrix的功能,因为它从未在您的代码中执行过。可能是你释放了那里的矩阵。
还有最后一条评论,因为你在方法中调用了errorHandle(),如果有一些错误,你很可能没有释放一些mallocs
void multiplyMatrix(struct MatrixObject *matrix1, struct MatrixObject *matrix2){
int newColumns = matrix2->columns;
int newRows = matrix1->rows;
int* newNumbers = malloc(newColumns * newRows * sizeof(*newNumbers));
int counter = 0;
if(matrix1->columns != matrix2->rows){
errorHandle();
}
//...
这里调用了errorHandle,但是你几乎没有办法释放newNumbers,因为它从未作为引用传入。这意味着它只会浮动而永远不会干净。
我建议在errorHandle
之后分配newNumbers