【问题标题】:Segmentation error due to allocation issues?由于分配问题导致的分段错误?
【发布时间】:2017-06-03 22:48:15
【问题描述】:

您好,我是编码新手,最近遇到了难题

这个程序有一个分段错误调试,我认为它与为缓冲区数组或输入文件分配空间有关,因为在我寻找答案的过程中,那些作为解决方案不断弹出。 如果您知道我做错了什么,如果您告诉我而不是给我解决方案,我将不胜感激。此外,我完全不知道如何为任何东西分配内存,所以如果有人解释如何在上下文中为代码分配内存,那就太好了。

它应该读取这样一个结构的文件

2
3 4
3 4

其中 2 = 正在下载的文件数量,3 = 文件的 Kb/s(每行代表一个文件),以及 4 = 完成前的剩余时间。该程序应该输出一个文件,该文件具有下载所有内容所需的时间(请注意,当文件完成时速度会上升到其他文件)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
  FILE *in = fopen("download.in", "r");
  FILE *out = fopen("download.out", "w");
  int i, n, j, a, k, o;
  char buffer[100];

  fgets(buffer, 10, in);
  sscanf(buffer, "%d", &n);
  int tn[n];
  int xn[n];

  i = 0;
  while (i < n) {
    fgets(buffer, 100, in);
    sscanf(buffer, "%d %d", &tn[i], &xn[i]);
    ++i;
  }
  for (i = 0; i < n; ++i){
    for (j = i + 1; j < n; ++j){
      if (tn[i] > tn[j]){
        a =  tn[i];
        tn[i] = tn[j];
        tn[j] = a;

        a =  xn[i];
        xn[i] = xn[j];
        xn[j] = a;
      }
    }

  }
  i = 1;
  float b ;
  k = 0;
  o = 1;
  while(o < n){
    if(xn[o] == xn[o - 1]){
      k = tn[o] + tn[o - 1]
      ;
    }
    else{
      b = (tn[o] * xn[o]) / (tn[o] + tn[o - 1] + k);
      k = 0;
    }
    ++o;
  }


  fprintf( out, "%f", b  );

  fclose(in); fclose(out);


  return 0;
}

我知道它给出的答案不准确,但我想先修复分段错误,然后再处理

gdb r 然后 gdb bt 返回这个

(gdb) r 
Program received signal SIGSEGV, Segmentation fault.                                                                   
_IO_fgets (buf=0x7fffffffeb30 "", n=10, fp=0x7fffffffeac0) at iofgets.c:50                                             
50      iofgets.c: No such file or directory.                                                                          
(gdb) bt                                                                                                               
#0  _IO_fgets (buf=0x7fffffffeb30 "", n=10, fp=0x7fffffffeac0) at iofgets.c:50                                         
#1  0x0000000000400766 in main () at main.c:11                                                                         

codeblocks 表示代码正常,而我尝试提供的网站也表示存在分段错误。

【问题讨论】:

  • 做基本的错误处理——例如,检查fopen的返回值。
  • "codeblocks 说代码没问题"。 IDE 无法告诉您您的代码在功能上或逻辑上是否正确。那不是它的工作。它只告诉你你的代码可以编译。
  • fopen 失败,因为它找不到文件 download。这就是为什么在使用 in 或 out 之前检查 fopen 的返回值的原因。指定文件 download.outdownload.out 的完整路径,或者如果您使用的是 IDE,请将工作目录设置为当前目录
  • 其他问题:fprintf( out, "%f", b ); 可能在没有分配b 的情况下发生。你想用(tn[o] * xn[o]) / (tn[o] + tn[o - 1] + k);进行整数除法还是用浮点除法?
  • 嗯好的 download.in 在同一个文件夹中,fopen 不返回 null 。让我还澄清一下,.out 文件已被编辑并且代码在我的电脑上运行良好,但我试图提交它以检测分段错误的网站。

标签: c segmentation-fault


【解决方案1】:

这是修复了段错误的代码。我必须 (1) 指定绝对路径和 (2) 将循环更改为 for 循环。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    FILE *in = fopen("/home/developer/CLionProjects/untitled4/download.in", "r");
    FILE *out = fopen("/home/developer/CLionProjects/untitled4/download.out", "w");
    int i, n, j, a, k, o;
    char buffer[100];

    fgets(buffer, 10, in);
    sscanf(buffer, "%d", &n);
    int tn[n];
    int xn[n];

    for (i = 0; i < n; i++) {
        if (!fgets(buffer, 100, in)) break;
        if (sscanf(buffer, "%d %d", &tn[i], &xn[i]) < 2) break;
    }


    for (i = 0; i < n; ++i) {
        for (j = i + 1; j < n; ++j) {
            if (tn[i] > tn[j]) {
                a = tn[i];
                tn[i] = tn[j];
                tn[j] = a;

                a = xn[i];
                xn[i] = xn[j];
                xn[j] = a;
            }
        }

    }
    i = 1;
    float b;
    k = 0;
    o = 1;
    while (o < n) {
        if (xn[o] == xn[o - 1]) {
            k = tn[o] + tn[o - 1];
            fprintf(out, "Some number: %d\n", k);
        } else {
            b = (tn[o] * xn[o]) / (tn[o] + tn[o - 1] + k);
            k = 0;
            fprintf(out, "Some number: %d\n", k);
        }
        ++o;
    }

    fclose(in);

    const char *text = "Write this to the file";
    fprintf(out, "Some text: %s\n", text);

    fclose(out);

    int c;

    FILE *file;
    file = fopen("/home/developer/CLionProjects/untitled4/download.out", "r");
    if (file) {
        while ((c = getc(file)) != EOF)
            putchar(c);
        fclose(file);
    }

    return 0;
}

【讨论】:

  • 每个输入和转换都应该验证。如果fgets(buffer, 10, in);sscanf(buffer, "%d", &amp;n); 失败,如何处理错误?然后在int tn[n];int xn[n]; 中使用'n' 的什么值?为什么10 用在fgets(buffer, 10, in); 中?为什么不fgets(buffer, sizeof *buffer, in);?或者,更好的是,定义一个常数,例如#define MAX 100char buffer[MAX] = ""; 然后是fgets(buffer, MAX, in);
猜你喜欢
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 2010-12-20
  • 1970-01-01
相关资源
最近更新 更多