0

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!

3
  • Undefined behavior != "instant guaranteed crash". (if only it were!) Commented Oct 27, 2014 at 21:10
  • Minor thing: sizeof(char) is 1, always. That's because sizeof(char) is the unit used to measure sizes in C; it's impossible for it to be anything else (even if you're on really weird hardware with e.g. 15-bit bytes). So when allocating char buffers, you never need sizeof. Commented Oct 27, 2014 at 21:14
  • Thanks Leushenko, then I understand that instead of sizeof(char) I can put the variable p directly that contains the number of the chars of the number. Commented Oct 27, 2014 at 21:22

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Basically I Need to know how to allocate memory and fill the str_fact.
0
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.

5 Comments

Thanks, You answered my first question. The second, in the structure definition I have char *str_fact. In every row I need to fill one value, but I don't know how.
No sorry I still don't understand. You are filling str_fact with fact_table[i].str_fact = (char *)malloc(6*sizeof(char)); and sprintf(fact_table[i].str_fact,"test"); I'm not sure what you are trying to improve. Sorry. :(
Sure it's valid. There are other ways but it's perfectly valid and readable. Just make sure you free it correctly when not required.
Thanks Nostromoo, but now I have the issue that I describe in the new edited question. Do you have any idea?
Ah yes I see your problem. You are allocating memory correctly. But you are corrupting it. This is hidden problem from first issue. First make sure you allocate the right amount, fact_table = (struct fact_entry *)malloc(sizeof(struct fact_entry) * n); But also your loop is wrong as you are are iterating over n+1 items. Change it to for (i = 0; i < n; i++).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.