识别导致分段错误(核心转储)的错误

Posted

技术标签:

【中文标题】识别导致分段错误(核心转储)的错误【英文标题】:Identify error causing Segmentation fault (core dumped) 【发布时间】:2022-01-02 12:57:58 【问题描述】:

我是 c 编程新手。决定通过做cs50开放课件中的一些问题集来学习。以下代码产生分段错误(核心转储)错误。我不明白为什么。我读过一个分段错误与访问您无权访问的内存有关。我看不出是什么原因造成的。我假设它与指针有关。我是指针的新手。谢谢。

    #include <stdio.h>

// https://cs50.harvard.edu/x/2021/labs/1/population/

float yearly_llamas(float starting_population) 
    // returns number of llamas at the end of the year
    float born = starting_population / 3;
    float died = starting_population / 4;
    float end_of_year_pop = starting_population + born - died;

    return end_of_year_pop;


int main(void) 
    
    // use floats for precision
    float *start_population;
    float *end_population;

    // set start lower limit
    int start_min = 9;

    
    // make sure input for starting population is greater than or equal to 9
    do 
        printf("Starting population: ");
        scanf("%f", start_population);
     while (*start_population < start_min);
    
 

    // get ending population, make sure greater than or equal to the starting population
    do 
        printf("Ending population: ");
        scanf("%f", end_population);
     while (*end_population < *start_population);

    // print for verification
    printf("%f\n", *start_population);
    printf("%f\n", *end_population);

    float end_pop = yearly_llamas(*start_population);

    printf("Llamas at the end of the year: %f\n", end_pop);


  return 0;

【问题讨论】:

现在是学习调试的好时机。在调试器中运行您的程序,它会将您指向触发 seg 错误的确切代码行。也可以使用调试器来跟踪/检查代码流和变量值。 float *start_population; 声明了一个未初始化的指针。 scanf("%f", start_population); 尝试读取数据并将其写入该指针。这个故事的寓意是不要使用指针,如果你不需要,但如果你确保它们指向有效的内存。在你的情况下使用float sp; scanf("%f", &amp;sp); float *start_population; scanf("%f", start_population); 这是行不通的,因为start_population 是一个未初始化的指针。试试float start_population; scanf("%f", &amp;start_population); 【参考方案1】:

您声明了一个指向浮点数的指针,但该指针没有指向任何内容,因为您没有为其分配地址。

更改这些行

float *start_population;
float *end_population;

float f_start_population;
float f_end_population;
float *start_population = &f_start_population;
float *end_population = &f_end_population;

应该解决分段错误。

【讨论】:

【参考方案2】:

虽然其他答案告诉您解决方案,但我想强调查找(和解决)此类问题的方法:使用调试器。它是程序员的重要工具,最好早点学会使用。 在这种情况下,您的问题很简单,可以使用任何调试器轻松找到。稍后,当您将使用更复杂的代码和多线程时,在尝试解决(复杂)问题时将很难学会使用它。请尝试使用调试器自行解决此问题。

如果你在 Linux 中,你可以使用 gdb 并运行代码直到它崩溃。然后,您检查回溯 (bt) 以查看最后执行的行。最后,在崩溃的前一行定义一个断点(p #n,其中#n 是行号),然后检查值(p $variable$variable 变量的名称)并尝试查看为什么它不起作用。

使用 GUI 调试器应该更容易(例如使用 Visual Studio 或 Code::blocks)。

【讨论】:

【参考方案3】:

当您像 float *f; 那样声明指针变量 f 时,您只能在指针实际上指向您保留的内存(该术语已分配)时“使用”它。您可以使用malloc() 函数在“堆”上分配变量,或者更简单地,通过编写float my_float; 并使用它在堆栈上创建一个单独的变量(称为自动变量)。所以你得到:

float my_startfloat;
float *start_population = &my_startfloat;

也就是说,我只会声明一个浮点(第一)行,然后在适当的情况下使用它的地址:&amp;my_startfloat。例如:

 float my_startfloat;
 scanf("%f", &my_startfloat);

【讨论】:

以上是关于识别导致分段错误(核心转储)的错误的主要内容,如果未能解决你的问题,请参考以下文章

获取“分段错误核心转储”

分段错误(核心转储)

运行我的代码时出现分段错误(核心转储)问题

pyqt5 中的分段错误(核心转储)

c中的分段错误(核心转储)

编程求解器的分段错误(核心转储)