C - 检测到堆栈粉碎
C - stack smashing detected
我需要对矩阵 A 执行一个非常简单的就地 LU 分解。我使用的是高斯消元法,我想用 3x3 矩阵对其进行测试。问题是,我一直收到 stack smashing
错误,我不知道为什么。我在我的代码中没有看到任何问题,它可以做到这一点。你有什么想法吗?
问题可能出在分解块中。
###My code:###
#include <stdio.h>
int main() {
int n = 3; // matrix size
int A[3][3] = {
{1, 4, 7},
{2, 5, 8},
{3, 6, 10}
};
printf("Matrix A:\n");
for( int i=0; i < n; i++ ) {
for( int j=0; j < n; j++ ) {
printf("%d ", A[i][j]);
if ( j % 2 == 0 && j != 0 ) {
printf("\n");
}
}
}
// FACTORIZATION
int k;
int rows;
for( k = 0; k < n; k++ ) {
rows = k + k+1;
A[rows][k] = A[rows][k]/A[k][k];
A[rows][rows] = A[rows][rows] - A[rows][k] * A[k][rows];
printf("k: %d\n", k);
}
printf("Matrix after decomp:\n");
for( int i=0; i < n; i++ ) {
for( int j=0; j < n; j++ ) {
printf("%d ", A[i][j]);
if ( j % 3 == 0 && j != 0 ) {
printf("\n");
}
}
}
return 0;
}
您的错误很可能在这里:
rows = k + k+1;
A[rows][k] = A[rows][k]/A[k][k];
A[rows][rows] = A[rows][rows] - A[rows][k] * A[k][rows];
这意味着rows
遍历值1、3、5;然后用于访问只有三个元素的数组。这确实会溢出,因为其中唯一有效的偏移量是 1。
编辑:查看您的 Matlab 代码,它正在做一些完全不同的事情,因为 rows = k + 1:n
将 rows
设置为一个小向量,然后它使用拼接矩阵,C 不支持作为原语的东西。您需要使用显式循环重新实现它和矩阵乘法A(rows, k) * A(k, rows)
。
您的原始 Matlab 代码是(Matlab 具有从 1 开始的索引):
for k = 1:n - 1
rows = k + 1:n
A(rows, k) = A(rows, k) / A(k, k)
A(rows, rows) = A(rows, rows) - A(rows, k) * A(k, rows)
end
rows = k + 1:n
的作用是设置 rows
来表示一个范围。表达式A(rows, k)
实际上是对矩阵的向量形切片的引用,Matlab可以将向量除以标量。
在最后一行,A(rows, rows)
是一个矩阵形状的切片,A(rows, k) * A(k, rows)
是一个矩阵乘法,例如将维度 (1,3) 和 (3,1) 的矩阵相乘得到 (3,3) 之一。
在 C 中,您不能使用内置的 =
和 /
运算符来做到这一点。
C 等价物是:
for ( int k = 0; k < n - 1; ++k )
{
// A(rows, k) = A(rows, k) / A(k, k)
for ( int row = k + 1; row < n; ++row )
A[row][k] /= A[k][k];
// A(rows, rows) = A(rows, rows) - A(rows, k) * A(k, rows)
for ( int row = k + 1; row < n; ++row )
for ( int col = k + 1; col < n; ++col )
A[row][col] -= A[row][k] * A[k][col];
}
(免责声明:未经测试!)
第一部分很简单:向量中的每个值都除以一个标量。
不过,第二行比较复杂。 Matlab代码包括矩阵乘法和矩阵减法;以及从矩阵中提取子矩阵的操作。如果我们试图将其直接翻译成 C,那将非常复杂。
我们需要使用两个嵌套循环遍历行和列来对方阵执行此操作。
我需要对矩阵 A 执行一个非常简单的就地 LU 分解。我使用的是高斯消元法,我想用 3x3 矩阵对其进行测试。问题是,我一直收到 stack smashing
错误,我不知道为什么。我在我的代码中没有看到任何问题,它可以做到这一点。你有什么想法吗?
问题可能出在分解块中。
###My code:###
#include <stdio.h>
int main() {
int n = 3; // matrix size
int A[3][3] = {
{1, 4, 7},
{2, 5, 8},
{3, 6, 10}
};
printf("Matrix A:\n");
for( int i=0; i < n; i++ ) {
for( int j=0; j < n; j++ ) {
printf("%d ", A[i][j]);
if ( j % 2 == 0 && j != 0 ) {
printf("\n");
}
}
}
// FACTORIZATION
int k;
int rows;
for( k = 0; k < n; k++ ) {
rows = k + k+1;
A[rows][k] = A[rows][k]/A[k][k];
A[rows][rows] = A[rows][rows] - A[rows][k] * A[k][rows];
printf("k: %d\n", k);
}
printf("Matrix after decomp:\n");
for( int i=0; i < n; i++ ) {
for( int j=0; j < n; j++ ) {
printf("%d ", A[i][j]);
if ( j % 3 == 0 && j != 0 ) {
printf("\n");
}
}
}
return 0;
}
您的错误很可能在这里:
rows = k + k+1;
A[rows][k] = A[rows][k]/A[k][k];
A[rows][rows] = A[rows][rows] - A[rows][k] * A[k][rows];
这意味着rows
遍历值1、3、5;然后用于访问只有三个元素的数组。这确实会溢出,因为其中唯一有效的偏移量是 1。
编辑:查看您的 Matlab 代码,它正在做一些完全不同的事情,因为 rows = k + 1:n
将 rows
设置为一个小向量,然后它使用拼接矩阵,C 不支持作为原语的东西。您需要使用显式循环重新实现它和矩阵乘法A(rows, k) * A(k, rows)
。
您的原始 Matlab 代码是(Matlab 具有从 1 开始的索引):
for k = 1:n - 1
rows = k + 1:n
A(rows, k) = A(rows, k) / A(k, k)
A(rows, rows) = A(rows, rows) - A(rows, k) * A(k, rows)
end
rows = k + 1:n
的作用是设置 rows
来表示一个范围。表达式A(rows, k)
实际上是对矩阵的向量形切片的引用,Matlab可以将向量除以标量。
在最后一行,A(rows, rows)
是一个矩阵形状的切片,A(rows, k) * A(k, rows)
是一个矩阵乘法,例如将维度 (1,3) 和 (3,1) 的矩阵相乘得到 (3,3) 之一。
在 C 中,您不能使用内置的 =
和 /
运算符来做到这一点。
C 等价物是:
for ( int k = 0; k < n - 1; ++k )
{
// A(rows, k) = A(rows, k) / A(k, k)
for ( int row = k + 1; row < n; ++row )
A[row][k] /= A[k][k];
// A(rows, rows) = A(rows, rows) - A(rows, k) * A(k, rows)
for ( int row = k + 1; row < n; ++row )
for ( int col = k + 1; col < n; ++col )
A[row][col] -= A[row][k] * A[k][col];
}
(免责声明:未经测试!)
第一部分很简单:向量中的每个值都除以一个标量。
不过,第二行比较复杂。 Matlab代码包括矩阵乘法和矩阵减法;以及从矩阵中提取子矩阵的操作。如果我们试图将其直接翻译成 C,那将非常复杂。
我们需要使用两个嵌套循环遍历行和列来对方阵执行此操作。