且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

免费()所引起分段错误

更新时间:2022-11-27 22:40:02

首先,你自己限制到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.