尝试解决 C 中未知的分段错误
我正在尝试学习如何使用快速傅立叶变换,并从 C 语言的数值食谱中复制了 FFT 算法,称为 four1。我编写了一个小函数测试,对一个简单函数进行傅里叶变换。但在执行时,程序返回分段错误。我找不到问题出在哪里,你能帮我吗?
#include <stdio.h>
#include <math.h>
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
void four1(float data[], unsigned long nn, int isign)
{
unsigned long n,mmax,m,j,istep,i;
double wtemp,wr,wpr,wpi,wi,theta;
float tempr,tempi;
n=nn << 1;
j=1;
for (i=1;i<n;i+=2) {
if (j > i) {
SWAP(data[j],data[i]);
SWAP(data[j+1],data[i+1]);
}
m=n >> 1;
while (m >= 2 && j > m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax=2;
while (n > mmax) {
istep=mmax << 1;
theta=isign*(6.28318530717959/mmax);
wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;
for (m=1;m<mmax;m+=2) {
for (i=m;i<=n;i+=istep) {
j=i+mmax;
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i] += tempr;
data[i+1] += tempi;
}
wr=(wtemp=wr)*wpr-wi*wpi+wr;
wi=wi*wpr+wtemp*wpi+wi;
}
mmax=istep;
}
}
void fourier_transform_test (FILE* output_file)
{
/*
This function serves as a test to see whether my implementation of the
fft is working or not.
*/
int n = 30; // number of samples
float x[n]; // array that holds all values for x
// misc
int i = 0;
printf("Running fourier transform tests...\n");
fprintf(output_file, "# x t\n");
// fill the array x with values to be transformed
for (i = 0; i <= (n - 1); i++)
x[i] = cos((2 * 3.1415 * i) / 10);
// according to the Numerical Recipies, I have to decrement the pointer to data
// by one to compensate for the zero-offset
four1(x-1, 64, 1);
// loop through the transformed array x and print results to a file
for (i = 0; i <= (n - 1); i++)
fprintf(output_file, "%i\t%f\n", i, x[i]);
fclose(output_file);
}
int main (int argc, char *argv[])
{
// open data_file to write results
FILE* file;
if (argc == 1)
file = fopen("results.dat", "w");
else
file = fopen(argv[1], "w");
fourier_transform_test(file);
return 0;
}
我正在使用最新的 Debian、gcc 4(非常确定)
对于那些想亲自阅读这本书的人: http://www.nrbook.com/a/bookcpdf/c12-2.pdf (其合法性)
I'm trying to learn how to use Fast Fourier Transform, and have copied the FFT algorithm from Numerical Recipies in C called four1. I have written a small function test that fourier transforms a simple function. But upon execution the program returns a segmentation fault. I can't find where the fault is can you help me?
#include <stdio.h>
#include <math.h>
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
void four1(float data[], unsigned long nn, int isign)
{
unsigned long n,mmax,m,j,istep,i;
double wtemp,wr,wpr,wpi,wi,theta;
float tempr,tempi;
n=nn << 1;
j=1;
for (i=1;i<n;i+=2) {
if (j > i) {
SWAP(data[j],data[i]);
SWAP(data[j+1],data[i+1]);
}
m=n >> 1;
while (m >= 2 && j > m) {
j -= m;
m >>= 1;
}
j += m;
}
mmax=2;
while (n > mmax) {
istep=mmax << 1;
theta=isign*(6.28318530717959/mmax);
wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;
for (m=1;m<mmax;m+=2) {
for (i=m;i<=n;i+=istep) {
j=i+mmax;
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i] += tempr;
data[i+1] += tempi;
}
wr=(wtemp=wr)*wpr-wi*wpi+wr;
wi=wi*wpr+wtemp*wpi+wi;
}
mmax=istep;
}
}
void fourier_transform_test (FILE* output_file)
{
/*
This function serves as a test to see whether my implementation of the
fft is working or not.
*/
int n = 30; // number of samples
float x[n]; // array that holds all values for x
// misc
int i = 0;
printf("Running fourier transform tests...\n");
fprintf(output_file, "# x t\n");
// fill the array x with values to be transformed
for (i = 0; i <= (n - 1); i++)
x[i] = cos((2 * 3.1415 * i) / 10);
// according to the Numerical Recipies, I have to decrement the pointer to data
// by one to compensate for the zero-offset
four1(x-1, 64, 1);
// loop through the transformed array x and print results to a file
for (i = 0; i <= (n - 1); i++)
fprintf(output_file, "%i\t%f\n", i, x[i]);
fclose(output_file);
}
int main (int argc, char *argv[])
{
// open data_file to write results
FILE* file;
if (argc == 1)
file = fopen("results.dat", "w");
else
file = fopen(argv[1], "w");
fourier_transform_test(file);
return 0;
}
I'm using latest Debian, gcc 4 (pretty sure)
For those of you who want to see the book for yourself:
http://www.nrbook.com/a/bookcpdf/c12-2.pdf
(its legit)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的数组中只有 30 个值,但您告诉 four1 您的数组有 64 个浮点数长。
You only have 30 values in your array but you're telling four1 that your array is 64 floats long.
您输入的浮点数数组的长度为
30
,但您将64
作为nn
值传递。然后将n
设置为两倍nn
,即 128:(顺便说一下,这一行只是一种混淆的方式来编写
n = nn * 2
code>,假设nn
是unsigned long
)。然后,该函数将访问高达
data[128]
的值,这相当于x[127]
,并且远远超出了数组的范围。Your input array of floats is of length
30
, but you pass64
as thenn
value.n
is then set to twicenn
, which is 128:(by the way, this line is just an obfuscatory way to write
n = nn * 2
, given thatnn
isunsigned long
).The function then accesses values up to
data[128]
, which is equivalent tox[127]
, and well beyond the bounds of the array.这是崩溃的堆栈跟踪:
由于这一行,您的output_file指针和堆栈帧被垃圾化,该行错误地假定x[]的大小超过30个浮点:
这里是通过到达数组来覆盖output_file指针的地方限制:
这是一本关于如何实现傅里叶变换的优秀书籍 - http://www.dspguide.com/
Here is a stacktrace of your crash:
your output_file pointer and also stack frame was garbaged because of this line, which incorrectly assumed size of x[] to be more than 30 floats:
And here is the place which overwrites output_file pointer by reaching over array limits:
Here is an excellent book about how to implement Fourier Transform - http://www.dspguide.com/
如果您告诉我们您正在使用什么操作系统和编译器,我们会更容易为您提供帮助。
也就是说,分段错误通常意味着指针错误。我猜你是手工复制的吧?然后寻找一个微小的拼写错误,例如
**p
的*p
或同样微不足道的东西。如果您使用的是 UNIX 系统,请将 corelimit 设置为较大的数字,然后再次运行。您很可能会得到一个核心转储。使用
gdb
找出实际错误发生的位置。我还会检查“
Usual C convention is thatindexs range from 0 to n-1”这一行,但 <= 测试表明 i 的范围将达到 n。
It will be easier to help if you tell us what operating system and compiler you're using.
That said, a segmentation fault usually means an error with pointers. I'm assuming you copied this by hand? Then look for a tiny typo, something like
*p
for**p
or something equally trivial.If you're on a UNIX system, set your corelimit to a large number, run it again. You'll get a coredump, most likely. use
gdb
to find out where the actual error occurs.I'd also check the line
Usual C convention is that indices range from 0 to n-1, but a <= test suggests i will range up to n.