Josh Avery
Josh Avery

Reputation: 9

C Dynamically allocated a struct in an array that is inside another struct

So to try to sum this up nicely, I have a main struct that is a catalog, it contains a counter(of the books it has), the capacity(total number of books it can support, can also grow), and an array of pointers that point to another struct that contains the book information.


typedef struct BooksInStock{
    int id;
    char title[MAX_TITLE];  // 38 Characters
    char author[MAX_AUTHOR]; // 20 Characters
    double level;
    int words;
}Books;


typedef struct Stock {
    Books *b;
    int count;
    int capacity;
} Stock;

The exact valgrind error is:

==23844== Invalid read of size 4
==23844==    at 0x401418: idComp (catalog.c:27)
==23844==    by 0x4E6FC62: msort_with_tmp.part.0 (in /usr/lib64/libc-2.17.so)
==23844==    by 0x4E6FBD7: msort_with_tmp.part.0 (in /usr/lib64/libc-2.17.so)
==23844==    by 0x4E6FFB6: qsort_r (in /usr/lib64/libc-2.17.so)
==23844==    by 0x401AE3: listAll (catalog.c:168)
==23844==    by 0x400C13: main (reading.c:73)
==23844==  Address 0x6e61724674666172 is not stack'd, malloc'd or (recently) free'd

I am assuming this is because I am not allocating my structs/array properly, but I haven't had to dynamically allocate an array of structs inside another struct before and I believe I am confusing myself.

EDIT: I was allocating the memory wrong see: C printing extremely weird values with printf

EDIT: As pointed out I forgot the method that calls idComp

void listAll(Catalog *cat)
{ // cat is just the catalog of books that have been read in already
    qsort(cat->b, cat->count, sizeof( Books ), idComp);  // idComp is called here
    if (cat->count == 0) {
        printf("No matching books");
    } else {
        printf("%5s %38s %20s %5s %7s", "ID", "Title", "Author", "Level", "Words");
        for (int i = 0; i < cat->count; i++) {
            printf("%5d %38s %20s %5.1f %7d", cat->b[i].id, cat->b[i].title,
            cat->b[i].author, cat->b[i].level, cat->b[i].words);
        }
    }
    printf("\n");
}

Upvotes: 0

Views: 61

Answers (1)

MikeCAT
MikeCAT

Reputation: 75062

cat->b points at an array of Books, so what are passed to comparision function of qsort are pointers to Books, not pointers to pointers to Books.

Threfore, the idComp function should be like this:

static int idComp( const void *aptr, const void *bptr )
{
  const Books *a = aptr;
  const Books *b = bptr;

  if ( a->id < b->id )
    return -1;
  if ( a->id > b->id )
    return 1;
  return 0;
}

Upvotes: 4

Related Questions