免费()所引起分段错误 [英] free() caused segmentation fault

查看:143
本文介绍了免费()所引起分段错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这个程序中,有一个分段错误。该程序可以打印出循环结束成功和循环结束,这意味着有没有read_name功能故障后段故障出现。但我不能在我的free_memory功能找出任何错误。谁能帮我找出?谢谢你。

输入文件:

  9
克林顿,希拉里R.
债券,博比·S.
债券,巴里L.
克林顿,威廉I.
克林顿,切尔西T.
布什,劳拉·M。
布什,小
布什,詹娜F.
布什,芭芭拉G.

程序:

 的#include<&stdio.h中GT;
#包括LT&;&malloc.h所GT;
#包括LT&;&string.h中GT;无效ALLOC(焦姓***,***炭首先,焦炭** mid_init,INT NUM);
无效read_names(FILE * INP,焦炭**姓,焦炭**首先,字符* mid_init,INT NUM);
无效free_memory(字符**姓,焦炭**首先,字符* mid_init,INT NUM);INT主(INT ARGC,CHAR *的argv [])
{
  INT NUM = 0;
  焦姓**,**首先,* mid_init;
  FILE * INP =的fopen(的argv [1],R);
  FILE * OUTP =的fopen(的argv [2],W);
  字符数组[79];  的fscanf(INP,%D,试验#);
  的printf(%d个\\ N,NUM);  与fgets(数组,79,INP);  ALLOC(安培;姓,和放大器;第一和放大器; mid_init,NUM);
  read_names(INP,姓,一是mid_init,NUM);
  free_memory(姓,一是mid_init,NUM);  FCLOSE(INP);
  FCLOSE(OUTP);  返回0;
}无效ALLOC(焦姓***,***炭首先,焦炭** mid_init,INT NUM)
{
  INT I;  *姓=(字符**)的malloc(NUM * sizeof的(字符*));
  *第一=(字符**)的malloc(NUM * sizeof的(字符*));
  * mid_init =(字符*)malloc的(NUM *的sizeof(字符));  对于(i = 0; I<民;我++)
  {
    (*姓)[I] =(字符*)malloc的(15 * sizeof的(炭));
    (*第一)[I] =(字符*)malloc的(10 * sizeof的(炭));
  }
}无效read_names(FILE * INP,焦炭**姓,焦炭**首先,字符* mid_init,INT NUM)
{
  字符*令牌,数组[79];
  字符DELIM [6] =,\\ n;
  INT I = 0;  与fgets(数组,79,INP);
  的printf(循环开始\\ n);  对于(i = 0; I<民;我++)
  {
      与fgets(数组,79,INP);
      的printf(%S,数组);       令牌= strtok的(数组,DELIM);
    的strcpy((姓[I]),令牌);
    的printf(%S(姓[I]));    令牌= strtok的(NULL,DELIM);
    的strcpy((第[I]),令牌);
    的printf(%S(第[I]));    令牌= strtok的(NULL,DELIM);
    * mid_init =令牌[0];
    的printf(%S \\ n,mid_init);    的printf(\\ n \\ n);  }
     的printf(\\ NLOOP结束\\ n);
}无效free_memory(字符**姓,焦炭**首先,字符* mid_init,INT NUM)
{
  INT I;  对于(i = 0; I<民;我++)
  {
    免费((姓)[I]);
    免费的((第一)[I]);
  }  免费(姓);
  免费(第一次);
  免费((mid_init));
}


解决方案

首先,你自己限制到14个字符的名字和9个字符的姓氏,所以这将是对的第一个的事情我会检查,你的名字是不是比这更长的时间。

如果是这样,你会复制他们的时候可能损坏记忆的舞台。

检查这是简单地打印长度的一种方法标记每次你设置的时间,如:

 令牌= strtok的(数组,DELIM);
的printf(DEBUG:标记长度为%d \\ n,strlen的(标记));

请腐败并不一定有立即可见,甚至永远。在这种情况下,什么是最有可能的情况是,你已经覆盖的重要一块在内存领域,在线控制信息,如一个内存块的大小或指向另一个内存块。

然而,没有code积极检查,当你写的内存,所以它可能只发现当你下次尝试做内存分配或取消分配调用。

您这样下次调用损坏后是你的免费通话而这几乎可以肯定它是被发现的,因为舞台上已损坏。

底线,超越写入分配的内存到底是不确定的行为。这意味着你不应该这样做。


如果事实证明你的名字的的时间过长(如你在评论中注明),你需要再问问自己,为什么你有多余的与fgets(数组79,INP); 在code。我明白为什么它需要在,以移动到下一行输入本着对的fscanf 。而那人做的工作做好。

不过,你得的其他的逐一 read_names 开始有效地扔掉列表中的名字。那将导致错误,因为,当你的code的认为的有文件中的 X 的名字,你扔掉的第一个问题这意味着只有 X - 1 剩余。可以这么说,是因为,当你开始打印出来的名字,从文件中第一次出现丢失。

如果您删除与fgets read_names 的开始,你会发现它的好。


  

顺便说一句,有一对夫妇的其他变动我会做的code。首先,你真的应该的检查的所有的malloc 要求的情况下,他们中的一个失败。这对所有功能的一般规则,可以失败,当你以后依靠他们没有失败。


  
  

第二,我不是一个真正的有史以来的sizeof(char)的乘以一个大风扇 - 这是由标准保证永远是 1 ,所以将其乘以堵塞了code,使得它的可读性。


In this program, there is a segmentation fault. The program can print out "loop end" successfully and segmentation fault appeared after "loop end", which means there is not error in read_name function. But I could not figure out any error in my free_memory function. Could anyone help me figure out? Thank you.

input file:

9
Clinton, Hillary R.
Bonds, Bobby S.
Bonds, Barry L.
Clinton, William I.
Clinton, Chelsea T.
Bush, Laura M.
Bush, George W.
Bush, Jenna F.
Bush, Barbara G.

program:

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

void alloc(char ***surname, char ***first, char **mid_init, int num);
void read_names(FILE *inp, char **surname, char **first, char *mid_init, int num );
void free_memory(char **surname, char **first, char *mid_init, int num);

int main(int argc, char *argv[])
{
  int num = 0;
  char **surname, **first, *mid_init;
  FILE *inp = fopen(argv[1], "r");  
  FILE *outp = fopen(argv[2], "w");
  char array[79];

  fscanf(inp, "%d", &num);
  printf("%d\n", num);

  fgets(array, 79, inp);

  alloc(&surname, &first, &mid_init, num);
  read_names(inp, surname, first, mid_init, num);
  free_memory(surname, first, mid_init, num);

  fclose(inp);
  fclose(outp);

  return 0;
}

void alloc(char ***surname, char ***first, char **mid_init, int num)
{
  int i;

  *surname = (char**)malloc(num * sizeof(char*));
  *first = (char**)malloc(num * sizeof(char*));
  *mid_init = (char*)malloc(num * sizeof(char));

  for(i=0; i<num; i++)
  {
    (*surname)[i] = (char*)malloc(15*sizeof(char));
    (*first)[i] = (char*)malloc(10*sizeof(char));
  }
}

void read_names(FILE *inp, char **surname, char **first, char *mid_init, int num )
{
  char *token, array[79];
  char delim[6] = ", .\n";
  int i=0;

  fgets(array, 79, inp);
  printf("loop begins\n");

  for(i=0; i<num; i++)
  {
      fgets(array, 79, inp);
      printf("%s", array);

       token = strtok(array, delim);
    strcpy( (surname[i]), token);
    printf("%s   ", (surname[i]));

    token = strtok(NULL, delim);    
    strcpy( (first[i]), token);
    printf("%s  ", (first[i]));

    token = strtok(NULL, delim);
    *mid_init = token[0];
    printf("%s\n", mid_init);

    printf("\n\n");

  }
     printf("\nloop ends\n");
}

void free_memory(char **surname, char **first, char *mid_init, int num)
{
  int i;

  for(i=0;i<num;i++)
  {
    free((surname)[i]);
    free((first)[i]);
  }

  free(surname);
  free(first);
  free((mid_init));
}

解决方案

First off, you're limiting yourself to 14-character first names and 9-character last names, so that would be the first thing I'd check, that your names aren't longer than this.

If they are, you'll probably corrupt the memory arena when copying them.

One way to check this is to simply print the length of token every time you set it, such as:

token = strtok(array, delim);
printf ("DEBUG: token length is %d\n", strlen (token));

Keep in mind that corruption does not necessarily have a visible immediately or even ever. In this case, what's most likely happened is that you've overwritten a vital piece of inline control information in the memory arena, such as a memory block size or a pointer to another memory block.

However, there's no code actively checking for that when you write to memory so it's probably only found when you next try to do a memory allocation or de-allocation call.

Your next call like this after the corruption is your free calls and that's almost certainly where it's being found, because the arena is corrupt.

Bottom line, writing beyond the end of allocated memory is undefined behaviour. That means you shouldn't do it.


If it turns out your names aren't too long (as you state in a comment), you need to then ask yourself why you have a superfluous fgets(array, 79, inp); in your code. I understand why it's needed in main so as to move to the next line after inputting the line count with a call to fscanf. And that one does its job well.

However, you have another one at the start of read_names which effectively throws away the first name in your list. That's going to cause problems because, while your code thinks there are X names in the file, you've thrown away the first one meaning that there are only X - 1 remaining. You can tell this because, when you begin to print out the names, the first one from the file appears to be missing.

If you remove the fgets at the start of read_names, you should find it's okay.

As an aside, there's a couple of other changes I'd make to the code. First you really should check all those malloc calls in case one of them fails. That's the general rule for all functions that can fail when you rely later on them not having failed.

Second, I'm not really a big fan of ever multiplying by sizeof(char) - this is guaranteed by the standard to always be 1, so multiplying by it clogs up the code and makes it less readable.

这篇关于免费()所引起分段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆