我正试着自学C语言,我正在为它看起来很基本的东西而挣扎。我有一个带有char指针的结构体,我想动态分配内存并在完成后释放它。我所理解的是,我需要为结构体和char指针分配内存,但看起来我错过了一些东西,因为我在sprintf
行上得到了分段错误。
作为理解和使用malloc
和free
的练习,我试图构建一个简单的程序,该程序将int
作为输入并输出一个包含从0到输入的所有数字的阶乘的表。每个表项都有它的索引(int
),阶乘的结果(long long int
)和结果,但是是字符数组格式(这是有问题的)。
这是我到目前为止的记录:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%sn", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str = NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %sn", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=0; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
我可能错过了一些非常明显的东西,并在为fact_table[i].str
分配内存时犯了一个愚蠢的错误,但我正在努力使其工作。
除了关于为n>= 2释放内存的注释之外,如果您查看malloc之后的测试:
if (fact_table[i].str = NULL) {
你将指针设置为NULL。你应该这样写:
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if ( fact_table[i].str == NULL) {
shout("malloc");
}
这里只是一些小小的建议。如果使用-Wall
编译,这个错误会在大多数编译器上生成警告:
fact.c: In function ‘main’:
fact.c:53:9: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (fact_table[i].str = NULL) {
^~~~~~~~~~
同样,为了确保如果你忘记了=
,编译器会报错,你可以比较变量和常量的值,把常量放在左边:如果你写if (NULL = fact_table[i].str)
,编译器会报错,并通知你错误。
我在我的设置中重现了这个问题。在程序正常运行之前,我们需要解决两个问题。
-
改变"fact_table[我]。str = NULL' to 'fact_table[i]。str == NULL'。前面的命令直接将'str'设置为NULL,这是不期望的。这就是你遇到段错误的原因。
-
在Free memory部分,您需要从索引2开始。你不能释放不属于你的内存。
下面的代码可以很好地工作在我的设置。希望能帮到你。
* *
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LIMIT 20
struct entry
{ /* Definition of each table entry */
int n;
long long int lli;
char *str;
};
void shout(char *m)
{
fprintf (stderr, "%sn", m);
exit (0);
}
int main (int argc, char *argv[])
{
int n;
int i;
struct entry *fact_table;
if (argc != 2)
shout("wrong parameters");
n = atoi (argv[1]);
if (n < 0)
shout("n too small");
if (n > LIMIT)
shout("n too big");
// Allocate memory for struct
fact_table = (struct entry*) malloc((n+1) * sizeof(struct entry));
if (fact_table == NULL) {
shout("malloc");
}
// Compute factorials
fact_table[0].n = 0;
fact_table[0].lli = fact_table[1].n = fact_table[1].lli = 1; // 0! = 1! = 1
fact_table[0].str = fact_table[1].str = "1";
for (i=2; i<=n; i++) {
fact_table[i].n = i;
fact_table[i].lli = i * fact_table[i-1].lli; // N! = N*(N-1)!
int digits = log10(fact_table[i].lli) + 1; // get number of digits of the result to allocate memory in consequence
fact_table[i].str = malloc((digits + 1)*sizeof(char));
if (fact_table[i].str == NULL) {
shout("malloc");
}
sprintf(fact_table[i].str, "%lld", fact_table[i].lli); // convert to string. ERROR HERE
}
// print factorial table
for (i= 0; i<=n; i++)
{
printf ("%d %lld %sn", fact_table[i].n, fact_table[i].lli, fact_table[i].str);
}
// Free memory
for (i=2; i<=n; i++) {
free(fact_table[i].str);
}
free(fact_table);
return 0;
}
* *