分配结构数组时出现段错误

Posted

技术标签:

【中文标题】分配结构数组时出现段错误【英文标题】:Segfault error when mallocing an array of structs 【发布时间】:2021-06-09 18:05:43 【问题描述】:

花了很长时间尝试调试此问题后,我来寻求您的帮助。 基本上在这个练习中,我试图读取字符串"31|Name1;23|Name2;15|Name3" 并将其存储在struct s_perso 的数组中,其中| 标记一个年龄的结束和一个名字的开始,而;正在标记一个新结构的开始。

这是给定的 ft_perso.h:

#include <string.h>
#ifndef FT__PERSO__H
#define FT__PERSO__H

typedef struct      s_perso

    char    *name;
    float   life;
    int     age;
    char    *profession;
   
                        t_perso;

#endif

我们将只使用该结构s_perso 中的数据agename

这是我的代码:

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

int     numberofstructs(char *str)

    int         i;
    int         length;

    i = 0;
    length = 0;
    if (str[0])
        length = 0;
    else
    
        while (str[i])
        
            if (str[i] == ';')
                length += 1;
            i++;
        
    
    return (length);


int     get_data_length(char *str, int i)

    int         length;

    length = 0;
    while (str[i] != '|' && str[i] != ';' && str[i] != '\0')
    
        length++;
        i++;
    
    return (length);


char    *get_data(char *str, int i)

    int j;
    char    *str2;

    j = 0;
    str2 = (char *)malloc(sizeof(char) * get_data_length(str, i) + 1);
    while (str[i] != '|' && str[i] != ';' && str[i] != '\0')
       
        str2[j] = str[i];
        i++;
        j++;
    
    str2[j] = '\0';
    return (str2);


t_perso     **ft_decrypt(char *str)

    int             i;
    int             j;
    t_perso         **textttt_perso;

    i = 0;
    j = 0;
    textttt_perso = (t_perso **)malloc(sizeof(t_perso **));
    *textttt_perso = (t_perso *)malloc(sizeof(t_perso *) * numberofstructs(str));
    
    while (j <= strlen(str) && str[j])
    
        if (str[j] == ';')
        
            i++;
            j++;
        
        textttt_perso[i]->age = atoi(get_data(str, j));
        j = j + get_data_length(str, j) + 1;
        textttt_perso[i]->name = get_data(str, j);
        j = j + get_data_length(str, j);
    
    textttt_perso[i+1] = 0;
    return (textttt_perso);


int     main(void)

    int i;
    t_perso **tab;
    i = 0;
    char        str[29] = "31|Name1;23|Name2;15|Name3";
    tab = ft_decrypt(str);
    while(i <= numberofstructs(str))
    
        printf("age = %d\n", tab[i]->age);
        printf("age = %s\n", tab[i]->.name);
        i++;
    

从我的调试中,我在第二次调用(当i = 1 并且我们正在处理t_perso **ft_decrypt(char *str) 的子字符串23 时)指令时出现段错误:

textttt_perso[i]-&gt;age = atoi(get_data(str, j));

我的猜测是我为结构数组本身或它可以包含的数组数量分配的内存是错误的。我无法指出这个问题......

提前感谢您的帮助,祝您有美好的一天!

【问题讨论】:

How do I work with dynamic multi-dimensional arrays in C? str[i] != '|' &amp;&amp; str[i] &amp;&amp; ';' 呃,这里有点不对劲。那是str[i] != ';' @KamilCuk 我的上帝简直不敢相信我写了那个,真可惜。该程序无限循环,但我正在尝试看看它可能来自哪里 【参考方案1】:

您永远不会为实际结构分配空间。在您的示例中:

textttt_perso = (t_perso **)malloc(sizeof(t_perso **));

为一个指针分配空间并且:

*textttt_perso = (t_perso *)malloc(sizeof(t_perso *) * numberofstructs(str));

为 3 个指针分配足够的空间。在某些时候,您需要为实际结构分配空间。

您还有其他问题。在numberofstructs() 中有if(str[0]),这将导致length 始终为零。同样在numberofstructs() 中,您计算​​分号。如果最后一个分号后有数据,则需要在length 中加 1。

如果数据不完美,这段代码中还会出现许多其他问题,但这里有一个ft_decrypt 的实现应该可以工作。初始 malloc 应该是保存指针数组。然后循环应该为每个数组条目分配一个结构。

t_perso** ft_decrypt(char* str)

  int i = 0;
  int j = 0;
  t_perso** textttt_perso;

  textttt_perso = malloc(sizeof(*textttt_perso) * numberofstructs(str));

  while (j <= strlen(str) && str[j])
  
    if (str[j] == ';')
    
      i++;
      j++;
    
    textttt_perso[i] = malloc(sizeof(*textttt_perso[i]));
    textttt_perso[i]->age = atoi(get_data(str, j));
    j = j + get_data_length(str, j) + 1;
    textttt_perso[i]->name = get_data(str, j);
    j = j + get_data_length(str, j);
  
  return (textttt_perso);

【讨论】:

这不是我想在这里做的吗?为 3 个t_perso * 类型化指针分配足够的空间? 我不是反对者,但在C 中转换mallocs 返回值没有任何好处。 @M. Nejat Aydin 我认为这样做是为了清楚起见。 @Jim Rhodes,请解释一下你会怎么做?我完全不知道如何实现这一目标。我试过这条线:*textttt_perso = (t_perso *)malloc(sizeof(t_perso) * numberofstructs(str) + 1); 但仍然收到段错误。 @badakzz 不,这无助于清晰。你可以考虑阅读this @badakzz 另外,使用 malloc 分配 n 元素的惯用方式,模拟数组定义 T a[n] 其中T 是一个类型,是a = malloc(n * sizeof *a);。那么你就不需要去碰malloc这一行,以防a的类型发生变化。

以上是关于分配结构数组时出现段错误的主要内容,如果未能解决你的问题,请参考以下文章

初始化数组时出现段错误

访问嵌套结构时出现段错误

尝试访问二维向量元素时出现段错误

C ++:访问unordered_map中的数据时出现段错误以设置

关闭文件时出现段错误

通过指针调用方法时出现段错误