2

I have such structures:

   typedef struct s_points
{
    double  x;
    double  y;
    double  z;
    int     color;
}               t_points;

typedef struct s_map
{
    int         width;
    int         height;
    t_points    ***points;
}               t_map;

I want to read and store an 2D array inside my ***points;, but i don't know how to allocate it properly. Here is my code(in map->width and map->height i store width and height of input array):

t_map   *validate(int fd, char *av)
{
    int         lines;
    int         j;
    char        *tmp;
    t_map       *map;
    t_points    **tmp_p;

    j = 0;
    if (!(map = (t_map*)malloc(sizeof(t_map))))
        error("ERROR: malloc error");
    if ((!(map->points = (t_points***)malloc(sizeof(t_points**) * map->height)))
        error("ERRROR!");
    while((get_next_line(fd, &tmp)) > 0)   //get_next_line will read input line by line
    {
        if (!(map->points[j] = (t_points**)malloc(map->width * sizeof(t_points*))))
            error("ERROR: malloc error");
        /* Some other code */;
        j++;
    }
    return(map);
}

It works, but when I trying to write something inside map->points[x][y]; I have segfault, so, as i understand, I have done mistake in memory allocation. So I can't understand how to do it in right way.

  • `***int` is not a 2D array, nor can it point to one. A pointer is never an array! Also being a 3-star (`***`) programmer is not a compliment. It almost always signals bad interfaces/design. Said that: read about pointers and array and dynamic memory allocation. They are explained in every C textbook. – too honest for this site Apr 11 '18 at 19:50

1 Answers1

2

You have one too many levels of indirection in points. You need one level for an array of pointers, and one more level for an array of t_points:

typedef struct s_map
{
    int         width;
    int         height;
    t_points    **points;
}               t_map;

Then allocate as follows:

if ((!(map->points = malloc(sizeof(t_points*) * map->height)))
    error("ERRROR!");
while((get_next_line(fd, &tmp)) > 0)   //get_next_line will read input line by line
{
    if (!(map->points[j] = malloc(map->width * sizeof(t_points))))
        error("ERROR: malloc error");
    /* Some other code */;
    j++;
}

Also, don't cast the return value of malloc.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Correct answer (upvoted) **but** please consider using a one-dimensional array instead and storing the data in [row-major or column-major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order). This will often be more efficient than a two-dimensional array due to cache locality and arguably even yields simpler code, as you don't need to allocate multiple levels of pointers. I.e., `t_points *array1d = malloc(width * height * sizeof(t_points))` – TypeIA Apr 11 '18 at 18:58
  • @TypeIA: That's as much wrong as using a jagged array here. The correct way is to use a 2D array and leave the index processing to the compiler. It is not a bit worse performing than manually calculating the addresses, but much less error-prone and more clear. It also lets the compiler optimise better as heuristics are mostly for simple and ideomatic patterns. – too honest for this site Apr 11 '18 at 19:54
  • @Olaf I respectfully disagree; refer to [this question](https://stackoverflow.com/questions/17259877/1d-or-2d-array-whats-faster) for a full(er) treatment. There is a reason the vast majority of image processing code out there uses one-dimensional arrays exclusively. – TypeIA Apr 11 '18 at 20:17
  • @TypeIA: The simple reason is most libraries are older than C99 which introduced VLAs. In addition it's people stuck with 1990ies' C noit acepting C has advanced and trying to talk users into rubbish code. Oh, and of course it's the "holy grail" of FORTRAN compatibility., even if there is no intend to ever use this language. Beginners should learn how to write **read- and maintainable** code in the first place, not compatibility to 1960ies languages without need. Re. "vast majority": The fast majority of humans and flies eat feces. Yet I wouldn't recommend it. (not implying it is the majority) – too honest for this site Apr 11 '18 at 20:34
  • @Olaf FORTRAN compatibility? Feces?! I will let my argument stand as-is and agree to (vehemently) disagree here...! – TypeIA Apr 11 '18 at 20:47