释放指针时出现分段错误
segmentation fault while freeing pointer
class matrix
{
public:
int nrow;
int ncol;
double **m;
matrix(int r, int c)
{
nrow = r; ncol = c;
m = (double**)malloc(nrow*sizeof(double*));
for(int i=0; i<nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<nrow; i++)
for(int j=0; j<ncol; j++)
m[i][j] = 0;
}
~matrix()
{
for(int i=0; i<nrow; i++)
{
printf("destructor loop: %d\n", i); fflush(stdout);
free(m[i]);
}
free(m);
}
matrix(const matrix& that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void operator=(const matrix &that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
for(int i=0; i<nrow; i++) // clear current m
free(m[i]);
free(m);
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void show()
{
printf(" Marix:\n");
for(int i=0; i<nrow; i++)
{
printf(" ");
for(int j=0; j<ncol; j++)
{
if(m[i][j] >= 0) printf(" ");
printf("%.6lf ", m[i][j]);
}
printf("\n");
}
printf("\n");
}
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
double det()
{
if(nrow != ncol)
{
printf("non-square matrix: (%d, %d)\n\n", nrow, ncol);
exit(1);
}
if(nrow == 1) return m[0][0];
if(nrow == 2)
{
double ans = m[0][0]*m[1][1] - m[1][0]*m[0][1];
return ans;
}
double ans = 0;
int sign = 1;
for(int i=0; i<nrow; i++)
{
printf("det[size:%d, %d] loop row: %d\n", nrow, ncol, i); fflush(stdout);
matrix a(2, 2);
a = cofactor(i, 0);
ans += (sign*a.det());
sign = sign*(-1);
}
return ans;
}
};
int main()
{
matrix c(3, 3);
c.m[0][0] = 2; c.m[0][1] = -3; c.m[0][2] = 1;
c.m[1][0] = 2; c.m[1][1] = 0; c.m[1][2] = -3;
c.m[2][0] = 1; c.m[2][1] = 4; c.m[2][2] = 5;
c.show();
printf("determinant: %lf\n", c.det());
return 0;
}
偶数3x3矩阵调用det函数时出现分段错误。
我没有使用复杂调试器的经验,但使用 printf 语句时,运行时错误似乎发生在析构函数中的循环迭代期间。我也尝试过使用 vector< vector< double >> 而不是 double**。我认为在那种情况下它不需要析构函数。然后它给了我一个“双重免费错误”。我知道它何时发生但无法在我的代码中找到错误。我也试过内联计算余因子而不是调用函数,但它没有帮助。
问题出在辅助因子函数中。您已在循环外声明 int x = 0, y = 0
。在 x(辅助因子矩阵的行,ans)的情况下,它很好。但是我们希望每次从新行开始时 y 为 0,即 y 应该与 j 同步,在 j==c
.
时跳过
发生的事情是您跳过第 0 行,因为 i==r
,然后在下一行 (i=1
) 中,您遍历列,跳过第 0 列,因为 j==c
,然后检查第 1 列,第 2 列,所以执行的代码是
ans.m[0][0] = m[1][1]
, y++
,
ans.m[0][1] = m.[1][2]
、y++
,然后我们完成了列。
我们增加 x(x=1
现在),我们转到下一行,第 2 行(i=2
),但 y=2
,而不是重置。所以下一行执行这段代码:
ans.m[1][2] = m[2][1]
(跳过第 0 列),
这是 ans
的边界,因为 ans
有 ncols-1 = 2
列。
当在辅助因子函数末尾调用 ans
的析构函数时,这会导致错误。我修复了余因子代码,这导致在为 3*3 矩阵调用 det 时没有错误。
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
int y = 0;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
为了调试,我推荐gdb。您可以使用 onlinegdb.com 将您的代码粘贴到此处,然后单击调试。然后通过break设置断点,然后运行,n为下一条指令,s为step into函数。您可以搜索以了解更多信息。
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
递增 y
的逻辑在这里被打破。做一个简单的心理实验。如果原始矩阵是 3x3,并且它们在这里被缩减为 2x2
矩阵,即您的 ans
,那么您希望 ans
中的每个值都在这里初始化,并且
ans.m[x][y] = m[i][j];
y++;
将被执行四次。由于 y
最初设置为 0 并且永远不会重置为 0,因此此赋值中使用的 y
的值范围从 0 到 3,因此,在某些时候,这将尝试将某些东西分配给 ans.m[x][3]
,这当然不存在,并且随之而来的是 hillarity。
看来这里的明显意图是重置
y=0;
作为外部 for
循环中的第一个业务订单,而不是一开始就一次。
class matrix
{
public:
int nrow;
int ncol;
double **m;
matrix(int r, int c)
{
nrow = r; ncol = c;
m = (double**)malloc(nrow*sizeof(double*));
for(int i=0; i<nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<nrow; i++)
for(int j=0; j<ncol; j++)
m[i][j] = 0;
}
~matrix()
{
for(int i=0; i<nrow; i++)
{
printf("destructor loop: %d\n", i); fflush(stdout);
free(m[i]);
}
free(m);
}
matrix(const matrix& that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void operator=(const matrix &that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
for(int i=0; i<nrow; i++) // clear current m
free(m[i]);
free(m);
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void show()
{
printf(" Marix:\n");
for(int i=0; i<nrow; i++)
{
printf(" ");
for(int j=0; j<ncol; j++)
{
if(m[i][j] >= 0) printf(" ");
printf("%.6lf ", m[i][j]);
}
printf("\n");
}
printf("\n");
}
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
double det()
{
if(nrow != ncol)
{
printf("non-square matrix: (%d, %d)\n\n", nrow, ncol);
exit(1);
}
if(nrow == 1) return m[0][0];
if(nrow == 2)
{
double ans = m[0][0]*m[1][1] - m[1][0]*m[0][1];
return ans;
}
double ans = 0;
int sign = 1;
for(int i=0; i<nrow; i++)
{
printf("det[size:%d, %d] loop row: %d\n", nrow, ncol, i); fflush(stdout);
matrix a(2, 2);
a = cofactor(i, 0);
ans += (sign*a.det());
sign = sign*(-1);
}
return ans;
}
};
int main()
{
matrix c(3, 3);
c.m[0][0] = 2; c.m[0][1] = -3; c.m[0][2] = 1;
c.m[1][0] = 2; c.m[1][1] = 0; c.m[1][2] = -3;
c.m[2][0] = 1; c.m[2][1] = 4; c.m[2][2] = 5;
c.show();
printf("determinant: %lf\n", c.det());
return 0;
}
偶数3x3矩阵调用det函数时出现分段错误。 我没有使用复杂调试器的经验,但使用 printf 语句时,运行时错误似乎发生在析构函数中的循环迭代期间。我也尝试过使用 vector< vector< double >> 而不是 double**。我认为在那种情况下它不需要析构函数。然后它给了我一个“双重免费错误”。我知道它何时发生但无法在我的代码中找到错误。我也试过内联计算余因子而不是调用函数,但它没有帮助。
问题出在辅助因子函数中。您已在循环外声明 int x = 0, y = 0
。在 x(辅助因子矩阵的行,ans)的情况下,它很好。但是我们希望每次从新行开始时 y 为 0,即 y 应该与 j 同步,在 j==c
.
发生的事情是您跳过第 0 行,因为 i==r
,然后在下一行 (i=1
) 中,您遍历列,跳过第 0 列,因为 j==c
,然后检查第 1 列,第 2 列,所以执行的代码是
ans.m[0][0] = m[1][1]
, y++
,
ans.m[0][1] = m.[1][2]
、y++
,然后我们完成了列。
我们增加 x(x=1
现在),我们转到下一行,第 2 行(i=2
),但 y=2
,而不是重置。所以下一行执行这段代码:
ans.m[1][2] = m[2][1]
(跳过第 0 列),
这是 ans
的边界,因为 ans
有 ncols-1 = 2
列。
当在辅助因子函数末尾调用 ans
的析构函数时,这会导致错误。我修复了余因子代码,这导致在为 3*3 矩阵调用 det 时没有错误。
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
int y = 0;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
为了调试,我推荐gdb。您可以使用 onlinegdb.com 将您的代码粘贴到此处,然后单击调试。然后通过break
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
递增 y
的逻辑在这里被打破。做一个简单的心理实验。如果原始矩阵是 3x3,并且它们在这里被缩减为 2x2
矩阵,即您的 ans
,那么您希望 ans
中的每个值都在这里初始化,并且
ans.m[x][y] = m[i][j];
y++;
将被执行四次。由于 y
最初设置为 0 并且永远不会重置为 0,因此此赋值中使用的 y
的值范围从 0 到 3,因此,在某些时候,这将尝试将某些东西分配给 ans.m[x][3]
,这当然不存在,并且随之而来的是 hillarity。
看来这里的明显意图是重置
y=0;
作为外部 for
循环中的第一个业务订单,而不是一开始就一次。