Dynanamic memory allocation- What malloc does ?

Go To Last Post
40 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I can write a program for dynamic memory allocation, but I don't know how it works

 

   I have written code 

/*GCC compiler
/* Hardware PC

#include<stdio.h> 
 
#include<stdlib.h>
          
int main ()
{  
  
 int *Ptr = NULL;
 Ptr = malloc (sizeof(Ptr));
  
 if (Ptr == NULL)
 {
     printf("Error\n");
 }
  
 else
 {
    printf("Memory is allocated \n");
     
    *Ptr = 1;
     
    printf("Ptr hold address -> %p \n", Ptr);
      
    printf("Value  %d  stored at ->  memory location %p \n", *Ptr, Ptr);
 }
  
 free(Ptr);
         
  return 0;     
}

Memory is allocated
Ptr hold address 00B313A8
Value  1  stored at ->  memory location 00B313A8

 

Malloc allocates a block of memory at runtime 

 

I do not understand what is going on

 int *Ptr = NULL;
 Ptr = malloc (sizeof(Ptr));

I have declared pointer that is null then in second line what we are assigning ?  What malloc does ?

This topic has a solution.
Last Edited: Sat. Feb 22, 2020 - 11:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Again, this is all standard textbook stuff!

 

sky33 wrote:
Memory is allocated
Ptr hold address 00B313A8
Value  1  stored at ->  memory location 00B313A8

 

Malloc allocates a block of memory at runtime 

 

You have actually described it all there - so where's the problem?

 

malloc() allocates a "blob" of memory, and tells you the location of that blob; ie, it gives you a pointer to it.

 

Obviously, this requires that you have a solid understanding of pointers - have you?

 

If not, you need to spend time in your textbook on pointers first!

 

sky33 wrote:
I have declared pointer that is null then in second line what we are assigning ?

A pointer is just like any other variable:

  • you can give it an initial value when you define it - here, that value is NULL;
  • you can change that value later in the program - here, it receives the return value from malloc();

 

In the code shown, you really don't need to initialise the pointer in its declaration - because you are immediately setting it with the return value from malloc().

 

Again, the return value from malloc() is a pointer to (ie, the address of) the memory that it allocated for you.

 

An important thing to note is that malloc() might fail to allocate any memory. In that case, it will return NULL.

 

Therefore, it is important to check the return value before using it!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 08:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
the return value from malloc() is a pointer to (ie, the address of) the memory that it allocated for you

SO perhaps you're asking, "why a pointer?"

 

With "normal" variables, you have to declare them in your source code - so they have a name at compile time; therefore, you can access them using name.

 

With dynamic allocation, the memory does not exist at compile time - so it cannot have a name.

 

Instead, you have to use a pointer, and you have to set that pointer to point to the location (the "address") of the dynamically-allocated memory.

 

malloc() tells you the location (the "address") of the dynamically-allocated memory as its return value.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sky33 wrote:

int *Ptr = NULL;
Ptr = malloc (sizeof(Ptr));

You are allocating space for something that is the sizeof a pointer.

I expect what you meant is to alocate space for something that is the sizeof an int (the sizeof the type that Ptr points to).

In which case it should be sizeof(*Ptr)

int *Ptr = malloc(sizeof(*Ptr));

You could also write this as

int *Ptr = malloc(sizeof(int));

But the first way means it still works  if you change int *Ptr to something else eg. long *Ptr.

The second way means you would also have to remember to change sizeof(int) to sizeof(long).

 

In your example, the sizeof a pointer is big enough for an int so it seems to work, but probably not doing quite what you expected.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

 

With "normal" variables, you have to declare them in your source code - so they have a name at compile time; therefore, you can access them using name.

 

With dynamic allocation, the memory does not exist at compile time - so it cannot have a name.

 

 

 

I understand, we need dynamic memory when we do not know how much memory needed

 

There are the three state of program,

 

1. Run time

2. Compile time

3. Execute  

 

compiler allocate Memory for variables  

 

Malloc allocates a  memory at runtime , What does it mean regarding run time vs compile time?

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sky33 wrote:
There are the three state of program,

 

1. Run time

2. Compile time

3. Execute  

No - 'Execute' and 'Run time' are the same.

 

What does it mean regarding run time vs compile time?

The clue is in the names!

 

  • Compile time is the time when you compile your source code
    (usually the same as 'Build Time' - which includes all the other steps of a complete build)
     
  • Run time is the time when the built, executable code is running in the target system.

 

EDIT

 

Some good diagrams illustrating the process of going from source code, through compiling, etc, to the executable on the Target:

 

https://www.avrfreaks.net/commen...

 

https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 10:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:
so it seems to work, but probably not doing quite what you expected.

Good catch!

 

And a classic example of code that's "wrong" - but still "works" !

 

Another: https://www.avrfreaks.net/commen...

 

EDIT

 

And it can happen in hardware, too: https://www.avrfreaks.net/commen...

 

#BadCodeWorks #WrongButWorks #WorksByLuck #ProvenProductSyndrome

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Mar 9, 2020 - 09:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

As to where/why you use malloc. Consider building an address book for example. You let the user type in names, addresses, contact details. Some names and addresses are longer than others and when you start you don't want to put a fixed limit on how many entries there can be in total. If you were to make fixed limits you could perhaps do something like:

typedef struct {
    char name[30];
    char addr[100];
    char phone1[12];
    char phone2[12];
    char email[128];
} contact_t;

contact_t contact_list[50];

but this means that name[] can never be more than 30 characters and on the occasion that the name is just "Fred" or "Dave" one entry wastes 26 (well 25) characters in the name[] field. Also perhaps some entries don't have an addr[] at all or maybe only one phone[] and perhaps the email is really just "foo@abc.com" in which case 128 characters is a complete waste.

Also this only allows for contact_list[50] so someone with a lot of contacts is going to be very disappointed when they try to add a 51st entry.

 

To combat all this you could use dynamic allocation using malloc(). Not only would the list not be limited to 50 entries - it can be as short or as long as memory would allow. But also all the fields in the struct don't need to be fixed sizes either. Instead of hoding char []  arrays you could just hold char * pointers then when a new record is typed in you look at the length of name/addr/email and whether phone1/phone2/etc are even present. Then you only malloc() enough bytes for each field to just hold what has been given so a name of "Fred" or "Dave" will just have 5 bytes allocated (yes 5, not 4 as you probably still want 0x00 end markers for each).

 

By only allocating what's needed both for the internal members of an entry but also for the number of items in the list you can make much more efficient use of what memory you have available rather than pre-allocating fixed size arrays that impose all kinds of limits on sizes. The name[] probably can now be "Djamolodine Abdujaporov" if you want it to be!

 

HOWEVER there is a price to pay for all this. On a PC you can generally treat memory as almost "infinite" - there's so much it probably never runs out. But on a micro you might only have 4KB or 8KB of memory so at some stage when you try to add the 57th or 73rd "long" entry there might be no more memory left. So every time you call malloc() you need to check to see if it returned 0 to say "all the memory has gone".

 

Also, as you later delete people from the address book you may well free() the memory that their entry was using but if name/phone/email/contact_list[N] entries are all different sizes then as you free() all those things you leave varying sized "holes" all over the "heap memory" where malloc makes its allocations from. When you later call malloc() to add new entries then it will try to re-use the holes but if you just had a "Clifford" using 9 byte and now want to create a "Christine" that uses 10 bytes it can't reuse th e9 byte "hole" so that is "wasted" (it might be reused later when another "Fred" or "Dave" comes along but then there might be 3 or 5 byte ibts and pieces left unused all over the place. This is known as "heap fragmentation" and can lead to the heap running out of available memory to allocate even when there are still hundreds of bytes but they are split into 2/3/4's all over the place.

 

Bottom line malloc()/free() are great om "inifinite memory" PCs but can be a serious problem on 1/2/4/8K micros!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
On a PC you can generally treat memory as almost "infinite"

Indeed.

 

@sky33: Also, when you write a PC program, you have no idea how much memory will be available on the user's PC at the time (s)he runs it - so it makes little sense to fix the sizes of things; and any limits would be purely arbitrary.

 

On the contrary, for a small microcontroller program, you know exactly how much memory there is - so you have to limit things accordingly.

 

And you (generally) have to do that at compile time.

 

There is a common beginner's misconception that malloc() somehow magically gives you "more memory"; but that is not true - you are still limited by the physical memory present in the system (PCs have the advantage of "virtual" memory).

In fact, as clawson mentioned, using malloc() adds overheads - so you actually end up with less memory available for you to use.

 

And, as mentioned earlier, you have to add code in your system to handle the case when malloc() fails - eg, because you're out of memory.

 

On a PC, it's easy to just put up an error box saying, "out of memory" - but that's generally not an option on a small, embedded microcontroller system

 

 

Bottom line malloc()/free() are great om "inifinite memory" PCs but can be a serious problem on 1/2/4/8K micros!

Indeed!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

As to where/why you use malloc. Consider building an address book for example. You let the user type in names, addresses, contact details. Some names and addresses are longer than others and when you start you don't want to put a fixed limit on how many entries there can be in total. If you were to make fixed limits you could perhaps do something like

 

suppose If I want to make a record of the marks of stuent studying in school. we do not know how many student are studying in school. I assume 500 students 

int student[500];

 

Compiler will allocate space to stores the marks of 500 students But if 510 students are in the school then the program will give an error.  if only 450 students are in the school then space for 50 students will waste 

 

We use dynamic memory allocation  

#include<stdio.h> 

#include<stdlib.h>

int main ()
{  

 int *Ptr = NULL;
 Ptr = malloc (sizeof(Ptr) * student_size);

 if (Ptr == NULL)
 {
     printf("Error\n");
 }

 else
 {
    printf("Memory is allocated \n");

    printf("Ptr hold address -> %p \n", Ptr);

 }

 free(Ptr);

  return 0;
}

 

 I don't know the student's size, so what should I consider the student's size ?

Last Edited: Wed. Feb 19, 2020 - 03:42 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sky33 wrote:
 I don't know the student's size

You mean you don't know the number of students?

 

In that case, you just dynamically allocate one record at a time

 

 what should I consider the student's size ?

That's the whole point - you don't have to put an arbitrary limit in the program!

 

You can just keep on adding more & more records - until you run out of memory.

 

sky33 wrote:

 int *Ptr = NULL;
 Ptr = malloc (sizeof(Ptr) * student_size);

No, that's wrong again - as   MrKendo  explained in #4

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Feb 19, 2020 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

We use dynamic memory allocation  

You kind of missed the point!

 

If you have an unknown number of students you don't make some "upfront guess" and then allocate a huge block to record all their data. The whole point of "dynamic" allocation is that you only allocate as much as you need at any one time - add to it as your requirements grow, remove from it as they shrink. 

 

So you allocate the student records one at a time. Each time a new student joins you allocate another one. 

 

Because such a list is of unknown length you typically implement the storage as a "linked list". 

 

So you may have recorded 3 students data so far and your list looks like this:

 

There is a separate struct pointer ("Students") that either points to the first entry in the list if there are some entries or NULL if none have been added yet.

 

Then you want to add a "new one". So you go to malloc() and ask it to allocate a new one:

 

 

This is created with no connection to the list so far.

 

Everything in this new entry probably starts at 0x00 (this is why calloc() may be a better choice than malloc()) so you can fill in the new details for this added student. Then you run along the existing list until you are "pointing" at the last entry and you set its "Next" field to the address of this new one that c/malloc() has just delivered and now there are 4 entries in your list:

 

 

So now you have a list with 4 entries in it. If the 2nd one you added now moves to a new town you want to remove them so you go along the list until you know the address of the one before and the one after. You set the Next field of the first one to the address of the third one and you have:

 

You can now call free() on the 2nd one you malloc()d and the memory it was occupying is returned to the free heap pool.

 

As you can see the storage here can grown and shrink. It is "dynamic" - it changes to adapt to your information storage requirements. That is why use of malloc() is "dynamic memory management". It changes at run time to adapt to the required needs.

 

Last Edited: Wed. Feb 19, 2020 - 04:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

We use dynamic memory allocation  

You kind of missed the point!

 

If you have an unknown number of students you don't make some "upfront guess" and then allocate a huge block to record all their data. The whole point of "dynamic" allocation is that you only allocate as much as you need at any one time - add to it as your requirements grow, remove from it as they shrink. 

 

So you allocate the student records one at a time. Each time a new student joins you allocate another one. 

 

Because such a list is of unknown length you typically implement the storage as a "linked list". 

 

I am very happy that I got chance to get knowledge with you people. This is a very good forum, here everyone responds very well.

 

@clawson You have spent a lot of time writing and drawing diagrams i appreciate your help and time 

 

#include<stdio.h>
#include<stdlib.h>

struct Node
{
  int Marks;
  struct Node *next;
};
  int main()
{
  struct Node* head = NULL;
  struct Node* second = NULL;
  struct Node* third = NULL;

  head  = malloc(sizeof(struct Node));
  second = malloc(sizeof(struct Node));
  third  = malloc(sizeof(struct Node));

  head->Marks = 60;       //assign marks of first student
  printf(" %d ", head->Marks);
  head->next = second;  // Link first node with second

  second->Marks = 70;     //assign marks of second student
  printf(" %d ", second->Marks);
  second->next = third;

  third->Marks = 43;     //assign marks to third student
  printf(" %d ", third->Marks);
  third->next = NULL;

  return 0;
}

 

Last Edited: Wed. Feb 19, 2020 - 05:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

sky33 wrote:
@clawson You have spent a lot of time writing and drawing diagrams i appreciate your help and time 
Not really - as you may have spotted those diagrams are generally a cut/paste exercise of something that actually took about 30 seconds to draw in the first place.

 

By the way I'm only reinventing the wheel here anyway - you'll see very similar diagrams in books and internet articles all over the place.

 

here's a few I got in a simple Google Image search for nothing more than "linked list":

 

 

Those are all pretty much the very same diagram I just drew.

 

Last Edited: Wed. Feb 19, 2020 - 05:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's the basic idea. Although it's still just a fixed number of entries - so not really showing the potential of dynamic allocation.

 

But, again, never use the pointer returned by malloc() before first checking that it's not NULL !

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Going back to your student example, another technique that can be used with dynamic allocation is to make an initial guess at the size.

So you think 500 is reasonable, allocate for 500.

If you run out of room, then re-allocate (realloc) to a larger size eg. 1000.

If you run out of room again, re-allocate again to a larger size eg. 2000 etc.

When you're done and you know the total number of students, if needs be you can re-allocate again back down to that size.

Or just leave it as it is, which might waste some memory but a lot better than statically allocating for thousands just to handle the occasional case where you have a very large number of students.

Plus, you no longer have a fixed upper limit to the program.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
sky33 wrote:
@clawson You have spent a lot of time writing and drawing diagrams i appreciate your help and time 
Not really - as you may have spotted those diagrams are generally a cut/paste exercise of something that actually took about 30 seconds to draw in the first place.

I have written some code after spending so much time

 

#include<stdio.h>
#include<stdlib.h>

struct Node
{
  int Marks;
  struct Node *next;
};

struct Node* newStudent(int n, struct Node *Ps) {
    struct Node *new = malloc(sizeof(*new));
           new->Marks = n ;
           new->next = Ps;
		   printf(" location of first member %p\n",new->Marks);
		   printf(" location of second member %p\n",new->next);
		   printf(" Pointer new point to memory location : %p\n",new);
    return new;
}

void Display(struct Node *Ps){
     struct Node *c;
     c = Ps;
     while (c!=NULL){
           printf(" %d\n",c->Marks);
           c = c->next;
           }

     }

int main (void )
{
    struct Node *Ps = NULL;  

    Ps = newStudent(63, Ps);  // Marks of first student
    Ps = newStudent(84, Ps);  // Marks of second student
    Ps = newStudent(72, Ps);  // Marks of third student
    Ps = newStudent(56, Ps);  // Marks of fourth student

   Display(Ps);

    return 0;
}

 

Here is output of program

 

 location of first member 00000041

 location of second member 00000000

 

 Pointer new point to memory location : 00B313A8

 

 location of first member 0000004E

 

 location of second member 00B313A8

 

 Pointer new point to memory location : 00B313D8

 

 location of first member 00000053

 

 location of second member 00B313D8

 

 Pointer new point to memory location : 00B30DD8

 

 location of first member 0000003F

 

 location of second member 00B30DD8

 

 Pointer new point to memory location : 00B30DE8

 

 63
 83
 78
 65

 

Now I am trying to make a diagram from the output of the program

 

Here is my diagram

 

I want to show location  in the diagram that pointer point in code.  I do not understand where should be location on diagram 

 

Would you help me to fill the correct  memory location in this diagram from the program output ?

Last Edited: Thu. Feb 20, 2020 - 11:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

New->Marks is not a pointer, but you print it as such. The print message says “location of first member...”
this is not true.

The output doesn’t seem to match the code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sky33 wrote:
I have written some code

Presumably, on a PC ?

 

So have you actually used the PC's debugger to step through the code and watch what's happening - as it happens ?

 

This is a lot more effective than using printfs, and you won't be confused by getting your printf formats wrong - as Kartman mentioned

 

EDIT

 

Your indentation is confusing

struct Node* newStudent(int n, struct Node *Ps) 
{
    struct Node *new = malloc(sizeof(*new));

    new->Marks = n ;
    new->next = Ps;

    printf(" location of first member %p\n",new->Marks);        // This is actually the VALUE of 'Marks' for the new node
    printf(" location of second member %p\n",new->next);
    printf(" Pointer new point to memory location : %p\n",new);

    return new;
}

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Thu. Feb 20, 2020 - 10:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
New->Marks is not a pointer, but you print it as such. The print message says “location of first member...” this is not true. The output doesn’t seem to match the code.

 

I have tested code on PC It give same output as I have shown in previous post 

printf("  %p\n",new->Marks);        // This is actually the locatiion of 'Marks' for the new node
printf(" %d \n",new->Marks);        // This is actually the VALUE of 'Marks' for the new node

see the difference between %p and %d 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

sky33 wrote:
I have written some code

Presumably, on a PC ?

 

So have you actually used the PC's debugger to step through the code and watch what's happening - as it happens ?

 

I haven't done yet I used mingw gcc compiler on windows 10. I write code on notepad and execute via command. it would be better to debug my code and see  actual result what is happening in code but I do not know how to debug code for mingw 

 

http://www.mingw.org/wiki/Getting_Started  I started looking on page but its more confusing 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There’s online C compilers and debuggers. Just a Google away...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman There’s online C compilers and debuggers. Just a Google away... [/quote wrote:

I found online https://www.onlinegdb.com/online_c_compiler

 

Can you help me to debug code

This compiler is showing the names of variables that I have not use in my code 

 

Debug -> start -> step into

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can’t see anything unusual. Where should i be looking?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

I can’t see anything unusual. Where should i be looking?

 

look at variable name in red mark

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

So have you actually used the PC's debugger to step through the code and watch what's happening - as it happens ?

sky33 wrote:
I haven't done yet I used mingw gcc compiler on windows 10. I write code on notepad and execute via command. it would be better to debug my code and see  actual result what is happening in code but I do not know how to debug code for mingw

So why not download a free, complete IDE - like Visual Studio Express.

 

https://visualstudio.microsoft.com/vs/express/

 

Other free IDEs are available but, as you're posting in AVRFreaks, that one has the advantage of being almost identical to Atmel Studio

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

sky33 wrote:
see the difference between %p and %d 

I think you need to go back to your textbook on that!

 

Changing the %p to %d does not affect whether the address or the value is used !

 

printf( "  %p\n", new->Marks );  // This does *not* print the address of new->Marks;
                                 // it prints the *value* of new->Marks - but formats it as if it were a pointer. 
                                 // Doing this is likely to give unexpected results!

 

If you wanted to print the address of new->Marks, you would have to do this:

printf( "  %p\n", & new->Marks ); // The '&' operator takes the address of new->Marks - and that is what gets printed.

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sky33 wrote:

Kartman wrote:

I can’t see anything unusual. Where should i be looking?

What IDE is that?

 

Again, this is AVRFreaks - so most people here are going to be most familiar with AVR-related IDEs - eg, Atmel Studio.

 

Hence my suggestion to use Visual Studio on the PC - as that is, essentially, the same as Atmel Studio.

 

In your screenshot, it looks like the debugger is showing you a whole load of internal detail of what's going on inside malloc().

You really don't need to be looking at that!

 

Although I did say that using a debugger will help you in stepping through the code, it really isn't much help to us - as all we can see is static screenshots, with no idea of what's gone on before.

 

So, for stuff to post to the forum for people to look at remotely, printfs are actually better!

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

awneil wrote:
In your screenshot, it looks like the debugger is showing you a whole load of internal detail of what's going on inside malloc().
The call stack confirms that - he's actually stepped into malloc() itself.

 

If this is all about learning the operation of the C language I'm not entirely sure I understand what it matters about the location of variables anyway. If I was exploring the add operator then in:

int add(int a, int b) {
    return a + b;
}

int main(void) {
    int x, y, z;
    
    x = 37;
    y = 53;
    z = add(x, y);
}

why would I actually care where in memory a,b,x,y,z, are? All that's important to me is to observe z being set to 90. Where it actually is does not matter.

 

Seem to me that it's the same when you malloc() a struct. I suppose it's true that in a linked list the next-> pointers are pointing to malloc'd structs but the actual values are almost entirely arbitrary. (and because of the way malloc fragmentation happens quite possibly pretty "random")

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Changing the %p to %d does not affect whether the address or the value is used !

you are correct that was my misunderstanding 

 

awneil wrote:

What IDE is that?

already mentioned post #21

 

I used mingw gcc compiler on windows 10.

 

 56
 72
 84
 63

 

 

Code in post #17 is example of linked list. I want to find out L1, L2, L3 and L4  ? That's what i'm having a problem with it 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Andy - don't further confuse the poor guy! Using an online tool eliminates the challenge of installing stuff on his PC.  For those of us who have Macs, there's Xcode which is the 'default' tool whereas for PC's there's too many choices.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your code output was:

 

location of first member 00000041

 location of second member 00000000

 

Pointer new point to memory location : 00B313A8

 

 location of first member 0000004E

 

 location of second member 00B313A8

 

 Pointer new point to memory location : 00B313D8

 

 location of first member 00000053

 

 location of second member 00B313D8

 

 Pointer new point to memory location : 00B30DD8

 

 location of first member 0000003F

 

 location of second member 00B30DD8

 

 Pointer new point to memory location : 00B30DE8

 

 

You wrote the code - surely figuring out which pointer address is where should be pretty simple? There's only 5 options!

Last Edited: Fri. Feb 21, 2020 - 10:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

awneil wrote:

What IDE is that?

sky33 wrote:
already mentioned post #21

In #21 you said you were just using command-line compiler and a text editor

 

I used mingw gcc compiler on windows 10.

That's just a compiler (plus linker, etc) - not an IDE !

 

 

Code in post #17 is example of linked list. I want to find out L1, L2, L3 and L4  ? That's what i'm having a problem with it 

As discussed, the printfs are wrong in that code.

 

So correct them, and re-post the fixed code along with the output it gives.

 

Post it as a reply - don't change the existing post!

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If that's what you are creating then you start with "Ps" pointing to NULL then you create a node and now Ps points to that (so it is "head pointer" in the diagram). As such if you got the result:

 

"Pointer new point to memory location : 00B313A8 "

 

then the node with 56 in it is located at that address. By implication that means the L3 pointer in the second node (moving right to left) holds that value. You then got:

 

"Pointer new point to memory location : 00B313D8 "

 

so that is where the node that holds 72 is located and also what the L2 pointer is set to point to.

 

The node with 84 is therefore at  00B30DD8 (BTW notice sudden jump in address allocation! As I said previously "almost pretty random"!), hence also the L1 value. Finally the node with 63 is at  00B30DE8 and that is also the value in "head pointer" (ie "Ps")

Last Edited: Fri. Feb 21, 2020 - 10:57 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1


In fact I guess this is the final diagram:

 

Obviously L1 / L2 / L3 contain the address of the thing to their right.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

In fact I guess this is the final diagram:

 

Obviously L1 / L2 / L3 contain the address of the thing to their right.

 

clawson Thanks  You answered my question

 

What do you think about below diagram 

 

 

#include<stdio.h>
#include<stdlib.h>

struct Node
{
  int Marks;
  struct Node *next;
};

struct Node* newStudent(int n, struct Node *Ps) {
    struct Node *new = malloc(sizeof(*new));
           new->Marks = n ;
           new->next = Ps;
		printf(" Location : %p \n", (void*)new);
    return new;
}

void Display(struct Node *Ps){
     struct Node *c;
     c = Ps;
     while (c!=NULL){
           printf(" %d\n",c->Marks);
           c = c->next;
           }

     }

int main (void )
{
    struct Node *Ps = NULL;  

    Ps = newStudent(63, Ps);  // Marks of first student
    Ps = newStudent(84, Ps);  // Marks of second student
    Ps = newStudent(72, Ps);  // Marks of third student
    Ps = newStudent(56, Ps);  // Marks of fourth student

   Display(Ps);

    return 0;
}

Output

 

 Location : 00B013A8
 Location : 00B013D8
 Location : 00B00DD8
 Location : 00B00DE8
 56
 72
 84
 63

 

Last Edited: Fri. Feb 21, 2020 - 05:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sky33 wrote:

What do you think about below diagram 

The n values in the diagram are backwards, 56 should be at the head of the list not the tail.

Other than that, I think you've got it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

MrKendo wrote:

sky33 wrote:

What do you think about below diagram 

The n values in the diagram are backwards, 56 should be at the head of the list not the tail.

Other than that, I think you've got it.

Good catch, you are correct 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do you need to show the addresses twice? Surely it was obvious what L1/2/3 must hold (always the address of the thing to the right)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used malloc in an embedded program just once and it was a mistake then.

In the case where there is just one variable-sized structure,

statically allocate all available memory to it.

Use the appropriate definition of available.

Iluvatar is the better part of Valar.