CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Struct malloc and pointers problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

Struct malloc and pointers problem
PostPosted: Fri Jun 17, 2011 12:09 pm     Reply with quote

Hi all

i have the following :
Code:

typedef struct tnode {
      struct tnode *prev;
      int16 value;
      struct tnode *next;
} myNode;
myNode *firstNode,*lastNode;


if i have in main :
Code:

 myNode *nod = &firstNode;
nod->value = 200;
   nod->next = malloc ( sizeof(myNode) );
   nod = nod->next;
   nod->value = 300;
   nod->next = malloc ( sizeof(myNode) );
   nod = nod->next;
   nod->value = 500;
   nod->next = NULL;


   while (true) {
      myNode *nd = &firstNode;
      while (!isLastNode(nd)) {
         lcd_gotoxy ( 5, 5, wTEXT );
         lcd_Nr ( show, nd->value );
         delay_ms ( 500 );
         lcd_Nr ( hide, nd->value );
         nd = nd->next;
      }
   }

the output is ok
taking in consideration that lcd nr and gotoxy works fine..


but i want to make a method for adding to my list.. myNode
so when i have :
Code:

void addToLast (myNode *nod, int16 value) {
   //this node
   nod->next = malloc ( sizeof(myNode) );
   nod = nod->next;
   //next nod
   nod->value = value;

   nod->next = NULL;
   lastNode = &nod;
}

and then
Code:

addtolast(nod,100);
addtolast(nod,200);
addtolast(nod,300);

it doesn't work like it should be.. :(

how can i pass to arg the pointer needed ?
Code:
addtolast(&nod,100); // it outputs more strange than without &


ccsc 4.120
pic 18f8527
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Jun 21, 2011 9:37 am     Reply with quote

A few things that I see at first glance:

1. firstNode and lastNode are both pointers that don't point to anything (at least you don't show us assigning them to something). You need to malloc some memory for them or set them to NULL (but don't use them until you malloc some memory).

2. The line
Code:
myNode *nod = &firstNode;

is a no no. The & gives the address of the pointer. You just want the pointer. Do this (no &):
Code:
myNode *nod = firstNode;


Save the & operator for when you want a pointer to point to a real object.


Now lets look at your function:

Code:

void addToLast (myNode *nod, int16 value) {
   //this node
   nod->next = malloc ( sizeof(myNode) );
   nod = nod->next;
   //next nod
   nod->value = value;

   nod->next = NULL;
   lastNode = &nod;
}


You are setting a pointer to the address of a pointer again here. Take out the & operator in that last line. The variable nod is a pointer already. I think this is what is getting you.

You are also forgetting to set the prev element.


As an aside:

You can make that function a bit more solid:
Code:

void addToLast (int16 value) {
   if(NULL == lastNode){  //First node allocation
      firstNode = lastNode = malloc ( sizeof(myNode) );  //may have to break this into 2 lines.
      lastNode->value = value;
      lastNode->next = NULL;
      lastNode->prev = NULL;
   }else if(NULL == lastNode->next){
      lastNode->next = malloc ( sizeof(myNode) );
      lastNode->next->prev = lastNode;  //set prev before the switch
      lastNode = lastNode->next;  //switch;
      lastNode->value = value;
      lastNode->next = NULL;
   }else{
      //This is an error condition...need to handle this somehow
   }

}


Mind you, I haven't had a chance to test that out (I am sure someone here could point out a mistake), but just trying to give an idea. Using it this way means the variable lastNode will always have the new value.

I would also take it a step further and use a struct to define a list type containing the firstNode and lastNode pointers, then pass that into the function I showed, rather than using globals.
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 4:44 am     Reply with quote

please test this in main

Code:


     myNode *firstNode, *lastNode;
     myNode *nod = firstNode;
     nod->prev = null;
     nod->value = ( long ) 11;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = ( long ) 32;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = ( long ) 14;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = ( long ) 451;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = ( long ) 11231;
     nod->next = NULL;
     lastNode = nod;
     printf ( "forward\r\n" );
     myNode *nodulet = firstNode;
     while (nodulet != NULL) {
         printf ( "%Ld\r\n", nodulet->value);
         nodulet = nodulet->next;
     }
     printf ( "backward\r\n" );
     nodulet = lastNode;
     while (nodulet != NULL) {
         printf ( "%Ld\r\n", nodulet->value );
         nodulet = nodulet->prev;
     }



I've test it in Proteus.. and output is :


forward
217
241
253
265
277
backward
183
185
277
265
253
241
217


what is happening ?
I have 11, 32,14,451 and 11231...
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 9:10 am     Reply with quote

Before doing any further tests, you absolutely have to correct the severe errors shown by jeremiah. You are writing a lot of data to nowhere.
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 9:43 am     Reply with quote

i can't quite explain why.. but this is ok

Code:

  firstNode = NULL;
     lastNode = NULL;
     myNode *nod = &firstNode;

     nod->prev = NULL;
     nod->value = 1;
     nod->next = malloc ( sizeof(myNode) );

     nod->next->prev = nod;
     nod = nod->next;
     nod->value = 2;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = 3;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = 4;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = 5;
     nod->next = NULL;
     myNode *lst = malloc(sizeof(myNode));
     lst = nod;
     printf ( "forward                %Ld \r\n", firstNode->value );
     nod = &firstNode;
     while (nod != NULL) {
         printf ( "%Ld \r\n", nod->value );
         nod = nod->next;
     }
     printf ( "backward                %Ld \r\n", lastNode->value );
     nod = &lst;
     while (nod != NULL) {
         printf ( "%Ld \r\n", nod->value );
         nod = nod->prev;
     }

     nod = &lst->prev;
     nod->next = malloc ( sizeof(myNode) );
     nod->next->prev = nod;
     nod = nod->next;
     nod->value = 6;
     nod->next = NULL;
     lst = nod;

     nod = &firstNode;
     nod->prev = malloc ( sizeof(myNode) );
     nod->prev->next = nod;
     nod = nod->prev;
     nod->value = -21;
     nod->prev = NULL;
     free (firstNode);
     firstNode = malloc(sizeof(myNode));
     firstNode = nod;

     //     free(lst);
     //     lst= malloc(sizeof (myNode));
     printf ( "forward                %Ld \r\n", firstNode->value );
     nod = &firstNode;
     while (nod != NULL) {
         printf ( "%Ld \r\n", nod->value );
         nod = nod->next;
     }
     printf ( "backward                %Ld \r\n", lastNode->value );
     nod = &lst;
     while (nod != NULL) {
         printf ( "%Ld \r\n", nod->value );
         nod = nod->prev;
     }




and output is :
Code:

forward                257
1
2
3
4
5
backward                0
0
5
4
3
2
1
forward                -21
1
2
3
4
5
6
backward                0
0
6
5
4
3
2
1
-21


even so... the first node is strange value..
forward 257
but the first value written from it is ok:-??
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 9:45 am     Reply with quote

are you refering to
Code:

firstNode= malloc(sizeof(myNode));
lastNode= malloc(sizeof(myNode));

??
noyz



Joined: 31 Jan 2009
Posts: 59

View user's profile Send private message

PostPosted: Thu Jun 23, 2011 9:55 am     Reply with quote

please try my example in proteus..

and then write back..
it seems that is really strange this pointer thing in ccsc

write the whole working example.

thanks
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Jun 28, 2011 9:14 am     Reply with quote

Your first mistake I see is here:
Code:

     firstNode = NULL;
     lastNode = NULL;
     myNode *nod = &firstNode;


You did good in initializing the pointers to NULL (good practice). However, you need to allocate memory for them before you use them. This is why you get the 257. You are pointing to random memory because you didn't allocate your own.

the line:
Code:
 myNode *nod = &firstNode;


will cause you problems because:
a) &firstNode is the address of the pointer firstNode
b) firstNode is NULL (not pointing to anything)

Try this instead:
Code:

     firstNode = NULL;
     lastNode = NULL;
     myNode *nod;

     nod = malloc(sizeof(myNode));

     firstNode = nod;
     lastNode = nod;


assuming I typed it correctly, this will allocate memory for your first node, which is something your current code is not doing at all.

It will then set firstNode and lastNode to point to that same node.


Also, you did something else wrong:
Code:

nod = &firstNode;
nod = &lst->prev;


This is a NO-NO. The variable firstNode is already a pointer and the same type as the variable nod. Do this instead:

Code:

nod = firstNode;
nod = lst->prev;


In your scenario, you shouldn't be using the & at all. It is used to get the address of a variable. If the variable is already a pointer, then you don't need the &.

Here is a 3rd problem, though you might not see it visually:
Code:

myNode *lst = malloc(sizeof(myNode));
lst = nod;


Using malloc is indeed important if the pointer doesn't have anything to point to. However, here you allocate memory and then immediately discard it. The memory you allocated with malloc is still there, but you no longer know where it is nor can use it because you set lst=nod. You have created what is called a "memory leak".

Memory that is allocated, that you no longer use should be "freed" using the free() function (but only once you are done).

At this point, I would say until you understand pointers, you shouldn't worry about getting this code to work as is. Take some time and study on how to use pointers in C (should be easy to google search for). Once you understand pointers, try again.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group