以下代码昨天编译好了一段时间,开始在一点上发出abort trap: 6
错误,然后再次正常工作一段时间,并再次开始给出相同的错误。我查找的所有答案都处理了一些固定指定长度的字符串。我在编程方面不是很有经验,所以对于为什么会发生这种情况有任何帮助表示赞赏。 (该代码用于计算Zeckendorf representation。)
如果我只是使用printf
逐个打印数字而不是使用字符串,则代码可以正常工作。
#include <string.h>
// helper function to compute the largest fibonacci number <= n
// this works fine
void maxfib(int n, int *index, int *fib) {
int fib1 = 0;
int fib2 = 1;
int new = fib1 + fib2;
*index = 2;
while (new <= n) {
fib1 = fib2;
fib2 = new;
new = fib1 + fib2;
(*index)++;
if (new == n) {
*fib = new;
}
}
*fib = fib2;
(*index)--;
}
char *zeckendorf(int n) {
int index;
int newindex;
int fib;
char *ans = ""; // I'm guessing the error is coming from here
while (n > 0) {
maxfib(n, &index, &fib);
n -= fib;
maxfib(n, &newindex, &fib);
strcat(ans, "1");
for (int j = index - 1; j > newindex; j--) {
strcat(ans, "0");
}
}
return ans;
}
答案 0 :(得分:4)
你的猜测是完全正确的:
char *ans = ""; // I'm guessing the error is coming from here
这使得ans
指向一个字符的只读数组,其唯一元素是字符串终结符。试图附加到这将写出界限并给你未定义的行为。
对于字符串,一个解决方案是dynamically allocate memory,如果您事先不知道大小,则需要reallocate来增加大小。如果这样做,请不要忘记为字符串终止符添加空格,并在完成后为free the memory添加空格。
答案 1 :(得分:1)
基本上,当您想要从C
中的函数接收字符串时,您有两种方法在您的情况下,zeckendorf()
函数可以确定字符串需要多少内存。第一个Fibonacci数小于参数的索引确定结果的长度。添加1以终止零,您知道需要分配多少内存。
因此,如果您选择第一种方法,则需要将另外两个参数传递给zeckendorf()
函数:char *buffer
和int size
并写入instead
的缓冲区ans
1}}。你需要有一些标记来知道它是否是while()
循环的第一次迭代。如果是,请在maxfib(n, &index, &fib);
之后检查条件index+1<=size
。如果condition为true,则可以继续执行您的功能。如果没有,您可以立即返回错误。
对于第二种方法,将ans
初始化为:
char *ans = NULL;
在maxfib(n, &index, &fib);
添加后:
if(ans==NULL) {
ans=malloc(index+1);
}
并继续像你一样。从函数返回ans
。记得在调用者中调用free()
,当不再需要结果来避免内存泄漏时。
在这两种情况下请记得将终止\0
写入缓冲区。
还有第三种方法。您可以将ans声明为:
static char ans[20];
在zeckendorf()
内。函数的行为与第一种方法相同,但缓冲区及其大小已经硬编码。我建议#define BUFSIZE 20
并将变量声明为static char ans[BUFSIZE];
,并在检查可用尺寸时使用BUFSIZE
。请注意,它仅适用于单线程环境。每次拨打zeckendorf()
都会覆盖以前的结果。请考虑以下代码。
char *a,*b;
a=zeckendorf(10);
b=zeckendorf(15);
printf("%s\n",a);
printf("%s\n",b);
zeckendorf()
函数始终返回相同的指针。因此a
和b
将指向同一缓冲区,其中将存储15
的字符串。因此,您需要将结果存储在某处,或者按正确的顺序进行处理:
a=zeckendorf(10);
printf("%s\n",a);
b=zeckendorf(15);
printf("%s\n",b);
根据经验,大多数(如果不是全部)Linux标准C库函数使用第一种或第三种方法。