为什么这个scanf会导致分段错误?

时间:2016-01-08 16:08:43

标签: c struct segmentation-fault scanf

我正在编写一个计算信息熵的程序,这是熵(H)的函数

  

H(X) = -sigma(i = 1 to n){p(x_i)*log2(p(x_i)}

     这里使用

base 2 log

然后这是我的程序

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <signal.h>

typedef struct vars {
    char *var;
    float prob;
} CHOISES;

float infocont(float x);
float entropy(CHOISES *, int);
void onsig(int);

int main(int argc, char *argv[])
{
    int i = 0;
    int siz = 0;
    float H = 0.0;

    printf("input the number of vars: ");
    scanf("%d", &siz);
    //printf("echo: %d\n", siz);

    CHOISES chs[siz];

    signal(SIGSEGV, onsig);

    for (i = 0; i < siz; i++) {
        printf("%d: ", i + 1);
        scanf("%s %f", chs[i].var, &chs[i].prob); /* HERE IS THE ERROR */
        //printf("echo: %s %f\n", chs[i].var, chs[i].prob);
    }

    H = entropy(chs, siz);

    printf("Entropy is %f\n", H);
}

void onsig(int signo)
{
    fprintf(stderr, "signal caught: %d\nSEGMENTATION FAULT\n", signo);
}

float infocont(float x) 
{
    return (log(1/x) / log(2));
}

float entropy(CHOISES chs[], int len)
{
     short i;
     float entropy;

     for (i = 0; i < len; i++) {
         entropy += chs[i].prob * infocont(chs[i].prob);
     }

     return entropy;
}

我的问题是当我输入第一个输入并点击输入时会产生分段错误。 我使用了调试器,我发现为结构分配数据会导致分段错误。 这是执行此代码行的时间

scanf("%s %f", chs[i].var, &chs[i].prob);

发生了分段错误。

但我在这段代码中无法想到错误。

为什么scanf()会出现分段错误?

2 个答案:

答案 0 :(得分:6)

chs[i].var是一个悬空指针。你必须首先malloc记忆。

chs[i].var = malloc(Max_str_len + 1);  //<--- this
scanf("%s %f", chs[i].var, &chs[i].prob);

答案 1 :(得分:1)

for (i = 0; i < 10; i++)
{
    printf("%d: ", i + 1);
    scanf("%s %f", chs[i].var, &chs[i].prob); /* HERE IS THE ERROR */
    //printf("echo: %s %f\n", chs[i].var, chs[i].prob);
}  

是的,这段代码确实引入了错误。

  1. 如果siz < 10怎么办?然后,这将导致另一个Segfault

    您应该使用for (i = 0; i < siz; i++)代替for (i = 0; i < 10; i++)

  2. chs[i].var没有指向任何有效的内存位置,因为它只包含垃圾,然后scanf()尝试将字符串存储在该内存位置,导致{{1} }

    您应首先使用SegFaultmalloc等分配内存。

  3. 将内存分配给calloc后,请勿忘记在chs[i].var之前检查它是否与NULL不相等,因为这可能会导致scanf() {1}}。

  4. 所以工作解决方案将是

    SegFault