• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C help; structs pointing to each other

Crusty

Lifer
I have the following code

Code:
typedef struct _a a;
typedef struct _b b;

struct _a {
  a *next_a;
  b *root;
};

struct _b {
  a *head;
};

a *alist;
b *blist;

void init() {
  alist = malloc(sizeof(a)*1000);
  assert(alist);
  memset(alist,0,sizeof(a)*1000);
  blist = malloc(sizeof(b)*1000);
  assert(blist);
  memset(blist,0,sizeof(b)*1000);
}

All of that works as expected, i can build my arrays and everything is dandy. Then I come along and call a destroy function like such
Code:
void destroy() {
  free(alist);
  free(blist);
}

Now here is where my problem is. Through one execution of the program there are many cycles of init()/destroy() before execution is finally terminated. After the first call to destroy() I can still access all the memory pointed to by blist and see all the values in the struct within the array. I can not do this for alist.

I first noticed this after the second call to init() when the memory still had all the old values from the first cycle of init()/destroy(). I popped into gdb and verified that free in fact is not doing anything to the memory, and all calls to malloc/memset on the pointer blist have no effects.

Any ideas why my blist array is not being set to all 0's after the 2nd call to init()?
 
Last edited:
I have the following code

Code:
typedef struct _a a;
typedef struct _b b;

struct _a {
  a *next_a;
  b *root;
};

struct _b {
  a *head;
};

a *alist;
b *blist;

void init() {
  alist = malloc(sizeof(a)*1000);
  assert(alist);
  memset(alist,0,sizeof(a)*1000);
  blist = malloc(sizeof(b)*1000);
  assert(blist);
  memset(blist,0,sizeof(b)*1000);
}

All of that works as expected, i can build my arrays and everything is dandy. Then I come along and call a destroy function like such
Code:
void destroy() {
  free(alist);
  free(blist);
}

Now here is where my problem is. Through one execution of the program there are many cycles of init()/destroy() before execution is finally terminated. After the first call to destroy() I can still access all the memory pointed to by blist and see all the values in the struct within the array. I can not do this for alist.

I first noticed this after the second call to init() when the memory still had all the old values from the first cycle of init()/destroy(). I popped into gdb and verified that free in fact is not doing anything to the memory, and all calls to malloc/memset on the pointer blist have no effects.

Any ideas why my blist array is not being set to all 0's after the 2nd call to init()?

It has been a while since I've programmed in C, but FWIW, free() requires a pointer to the object. Make sure the pointer is pointing at index 0.
 
your destroy function must perform some type of loop or recursion...
you are merely freeing the first struct in the list, but leaving the remaining ones behind.

Try something like:

void destroy(a)
{

if (a.next_a != NULL)
{ destroy(a.next_a); }
Free(a.next_a);

}


destructors are much easier to progam in C++.
 
your destroy function must perform some type of loop or recursion...
you are merely freeing the first struct in the list, but leaving the remaining ones behind.

Try something like:

void destroy(a)
{

if (a.next_a != NULL)
{ destroy(a.next_a); }
Free(a.next_a);

}


destructors are much easier to progam in C++.

I don't think so. Each of those pointers addresses an allocated block large enough for the entire list. If he isn't performing any arithmetic on them, and I don't see that he is, then free() should deallocate the whole block, and memset should also affect the whole block. I've looked at this twice now, and assuming we're seeing all the code I can't figure out why the memset would fail to overwrite the memory b_list points to.
 
I don't think so. Each of those pointers addresses an allocated block large enough for the entire list. If he isn't performing any arithmetic on them, and I don't see that he is, then free() should deallocate the whole block, and memset should also affect the whole block. I've looked at this twice now, and assuming we're seeing all the code I can't figure out why the memset would fail to overwrite the memory b_list points to.

I figured it out, wasn't anything wrong with the logic. In the code i wrote here I replaced some #define constants with 1000 for the malloc etc calls, problem was a typo in the constants causing me to call memset with a size of 0 instead of what I really wanted. Off by one digit...

You are correct about the list though, all the pointers inside of the structs are going to be pointing to objects in either of the lists, so there is no need to call free on those directly.
 
Back
Top