anacelto
anacelto

Reputation: 309

C - malloc in a loop with struct with pointer

I'm a beginner and I'm doing some exercises to learn C.

I'm working on dynamic memory allocation with structs and pointers. I have this struct:

struct fact_entry
{                               /* Definition of each table entry */
  int n;
  long long int lli_fact;       /* 64-bit integer */
  char *str_fact;
};

And this is my main code:

    int
main (int argc, char *argv[])
{
  int n;
  int i;
  struct fact_entry *fact_table;

  if (argc != 2)
    panic ("wrong parameters");

  n = atoi (argv[1]);
  if (n < 0)
    panic ("n too small");
  if (n > LIMIT)
    panic ("n too big");

/* Your code starts here */

int p;

      fact_table = (struct fact_entry *)malloc(n*sizeof(struct fact_entry));
      if(fact_table==NULL)
      {
    fprintf(stderr, "Out of memory, exiting\n");
    exit(1);
      }

for (i = 0; i<= n; i++)
    {

      fact_table[i].n = i;

      p = i;
      fact_table[i].lli_fact=1;
      while(p>0)
      {
    fact_table[i].lli_fact = p * fact_table[i].lli_fact;
    p--;
      }

      p = (int)log10(fact_table[i].lli_fact)+1;


     fact_table[i].str_fact = malloc(p);
     if(fact_table->str_fact==NULL)
      {
    fprintf(stderr, "Out of memory, exiting\n");
    exit(1);
      }
      sprintf(fact_table[i].str_fact,"%lld",fact_table[i].lli_fact);
    }


/* Your code ends here */

  for (i = 0; i <= n; i++)
    {

      printf ("%d %lld %s\n", fact_table[i].n, fact_table[i].lli_fact,
             fact_table[i].str_fact);
    }

  return 0;
}

The idea is to fill an array of 20 rows. Then every row have 3 columns. In the first column it shows the number of the line "i", in the second, the factorial of the number of the line, in the third the same that in the second but in string format.

I use the log10 to know how long will be the string.

The execution of the program shows this:

0 1 |g�!�2�
1 1 1
2 2 2
3 6 6
4 24 24
5 120 120
6 720 720
7 5040 5040
8 40320 40320
9 362880 362880
10 3628800 3628800
11 39916800 39916800
12 479001600 479001600
13 6227020800 6227020800
14 87178291200 87178291200
15 1307674368000 1307674368000
16 20922789888000 20922789888000
17 355687428096000 355687428096000
18 6402373705728000 6402373705728000
19 121645100408832000 121645100408832000
20 2432902008176640000 2432902008176640000

Line 0 should show 1 in the third column, what happens? It Appears somthing wrong with the malloc.

Thanks!

Upvotes: 0

Views: 2273

Answers (2)

Nostromoo
Nostromoo

Reputation: 284

fact_table = malloc(sizeof(struct fact_entry));

Why? In the first case I'm reserving memory for only one row, true? Why isn't causing a segmentation fault error?

Correct. But bad code does not imply a crash. You will write on memory that you have not expected to be allocated. But it is your memory! Depending on the implementation malloc might allocate a page size block of memory. This potentially means 4096 bytes. Only if you overwrite this might it crash. Or if you make another allocation which comes from that page might you see problems.

The second, why I can fill in the third column? I can't allocate memory.. I don't know how I can refer to every row, because I have a struct with a pointer in a loop... and I don't know how to define the iterations in the malloc.

Not sure I follow. You can either make a single malloc to allocate all the memory in one go. Then manually loop to fix up the address of str_fact into that block of memory. But that's unnecessarily complicated, although does mean you only have a single alloc. The answer provided by @SuperAgenten Johannes is the correct approach though IMO.

Upvotes: 0

Not sure that I understand your question.

fact_table = malloc(sizeof(struct fact_entry));

Would only allocate memory for one structure, to have a pointer to a 2d array you'd do

fact_entry **fact_table;
fact_table = malloc(sizeof(struct fact_entry) * RowAmount);
for(int row=0; row < RowAmount; row++)
    fact_table[row] = malloc(sizeof(struct fact_entry) * ColAmount);

Now you've allocated memory for a 2d array; every row has columns. And now to access the 2D array you could just do

fact_table[rowIndex][colIndex].myvar

When using Malloc, Realloc, Calloc etc, you've got to keep track of the array size yourself so keep variables for the Rows / Cols. If you want to leave out the columns and only have an array of Rows do the following.

fact_entry *fact_table;
fact_table = malloc(sizeof(struct fact_entry) * RowAmount);

Now you can access the structures by

fact_table[rowIndex].myVar

And don't forget to Free your objects

for(int Row=0; Row < RowAmount; Row++)
    free(fact_table[Row]);
free(fact_table);

Upvotes: 1

Related Questions