Thread: Queue operations giving undefined reference to malloc

  1. #1
    Registered User
    Join Date
    Nov 2018
    Posts
    13

    Question Queue operations giving undefined reference to malloc

    Hello,

    I am trying to implement a message storage (string type) and retrieval functionality, where I have 3 c files:

    main.c
    sender.c --> this will have send function
    receiver.c --> this will have receive function

    main.c needs to call the sender.c send to store the message and
    main.c needs to call the receiver.c receive to get the message in FIFO.

    So far to do this, I have created a new msgs.h file, sender.c and receiver.c
    But with this, I am getting compilation errors as my micro controller don't have malloc library. Is there any alternative and workable solution to do this?


    Code:
    //msgs.h
    #define MAXMESSGS 10
     
    struct node
    {
        char* data[10]; //--> I guess this is also not correct
        struct node *link;
    }*front, *rear;

    Code:
    //sender.c
    #include <msgs.h>
    send() {
    
      // SOME OTHER STUFF
    
    
        struct node *temp;
     
        temp = (struct node*)malloc(sizeof(struct node));
        temp->data = msg;
        temp->link = NULL;
        if (rear  ==  NULL)
        {
            front = rear = temp;
        }
        else
        {
            rear->link = temp;
            rear = temp;
        } 
    }
    Code:
    //receiver.c
    #include <msgs.h>
      receive ()
    {
    
      // SOME OTHER STUFF
    
       struct node *temp;
        temp = front;
         if (front == NULL)
        {
          printf("queue is empty \n");
         front = rear = NULL;
        }
        else
        {    
          msg=front->data;
          front = front->link;
          free(temp);
        }
    return msg;
    }
    Errors:
    Code:
    sender.c: undefined reference to malloc
    receiver.c: undefined reference to free
    Last edited by karumudi7; 11-28-2018 at 07:13 PM. Reason: updated msgs.h

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    Quote Originally Posted by karumudi7
    But with this, I am getting compilation errors as my micro controller don't have malloc library. Is there any alternative and workable solution to do this?
    Check the docs to see what does it provide for dynamic memory allocation. If nothing is provided, you might be able to create your own, e.g., create a memory pool (subject to the amount of memory you expect to be available), possibly using a global array, and then allocate from it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Nov 2018
    Posts
    13

    Question

    Quote Originally Posted by laserlight View Post
    Check the docs to see what does it provide for dynamic memory allocation. If nothing is provided, you might be able to create your own, e.g., create a memory pool (subject to the amount of memory you expect to be available), possibly using a global array, and then allocate from it.

    I don't need any dynamic allocations, just a simple queue that store say 5 messages. I never used malloc though, it was a reference. Any other ways to get this functionality, like an array?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    Quote Originally Posted by karumudi7
    I don't need any dynamic allocations, just a simple queue that store say 5 messages. I never used malloc though, it was a reference. Any other ways to get this functionality, like an array?
    Yes, you could use an array to implement a queue.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Nov 2018
    Posts
    13
    Quote Originally Posted by laserlight View Post
    Yes, you could use an array to implement a queue.
    I changed to Arrays, but I am getting multiple error messages when compiling the project:

    multiple definition of rear, front, size, CAPACITY

    Code:
    //mulmessgs.h
    
    
    int CAPACITY = 10;
    char* msgs[10];
    int size = 0;
    int rear = 9;
    int front = 0;
    Code:
    //sender.c
    #include <msgs.h>
    extern int size;
    extern int rear;
    extern int front;
    extern int CAPACITY;
    send() {
    
    
      // SOME OTHER STUFF
    
    
    
    
          rear = (rear+1)%CAPACITY;
        size++;
        msgs[rear] = msg;
        printf("Message in send: %s\n", msgs[0] );
    }
    Code:
    //receiver.c
    #include <msgs.h>
    extern int size;
    extern int rear;
    extern int front;
    extern int CAPACITY;
      receive ()
    {
    
    
      // SOME OTHER STUFF
    
    
         msg = msgs[front];
        front = (front+1)%CAPACITY;
    
    
    return msg;
    }
    Last edited by karumudi7; 11-28-2018 at 09:19 PM. Reason: added extern

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    That's because you're defining variables in a header, which is typically a bad idea as they would be multiply defined if you include the header in one than one translation unit. Also, I would bundle them up in a struct. If you really want a gloibal variable, declare it extern in the header, then define it in exactly one source file.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Nov 2018
    Posts
    13

    Question

    Quote Originally Posted by laserlight View Post
    That's because you're defining variables in a header, which is typically a bad idea as they would be multiply defined if you include the header in one than one translation unit. Also, I would bundle them up in a struct. If you really want a gloibal variable, declare it extern in the header, then define it in exactly one source file.
    I am not that familiar with structs, so trying in this way. I removed the header and declared and initialized the variables in sender.c and in receiver.c I am using as extern.
    But the output is something different. Am I doing anything wrong here?

    in main.c

    I called send two times and sent messages. "Hello" and "World".
    Then I called receive in main, in receive, I put a for loop to see what is there in the array before it calls the function. I am getting
    msgs[0] = 72
    msgs[1] = 69

    Code:
    //main.c
    extern char* msgs;
    
    main() {
    // some other
    
    void sd() {
    
    
        send(1, "Hello");
            send(2, "World");
        return OK;
    
    
    }
    
    
    void rec() {
    
    
        int i;
        for(i=0; i<2; i++). //debug
        {
            printf("\n value of msgs[%d]: %d", i, msgs[i]);
        }
        
           mssg = receive();
        kprintf("\n \n ---- Message recived: %s ----\n", mssg);
    
    
    }
    Output:
    Code:
    msgs[0] = 72
    msgs[1] = 69
    ---- Message recived: *)**SP*

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    Um, I don't even see an array declared in your code. I suggest that you post the smallest and simplest compilable program that demonstrates the error.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Nov 2018
    Posts
    13

    Question

    Quote Originally Posted by laserlight View Post
    Um, I don't even see an array declared in your code. I suggest that you post the smallest and simplest compilable program that demonstrates the error.
    Here are my code files (prototypes)... My project will compile first with all the files and on boot up, the main.c will start executes.

    Code:
    //------- main.c
    #include <SOME global header.h that has all those sender receiver c files>
     
    extern char* msgs;
    
    void main(void) {
    
    
    void snd() {
    
    
        send(1, "Hello");
        send(2, "World");
        return OK;
    }
    
    
    
    
    void rec() {
    
    
        int32 i;
        for(i=0; i<2; i++)
        {
            printf("\n value of msgs[%d]: %d", i, msgs[i]);
        }
        umsg32 mssg = receive();
        printf("\n \n ---- Message recived: %s ----\n", mssg);
    
    
     }
    
    
    }
    
    
    
    
    //---------------- sender.c 
    
    
    int CAPACITY = 10;
    char* msgs[10];
    int size = 0;
    int rear = 9;
    int front = 0;
    
    
    send ( 2 args ) {
    
    
        rear = (rear+1)%CAPACITY;
        size++;
        msgs[rear] = msg;
    }
    
    
    //--------------- receiver.c
    
    
    extern char* msgs;
    extern int size;
    extern int rear;
    extern int front;
    extern int CAPACITY;
    
    
    receive() {
    
    
        msg = msgs[0];    //Return First message
        front = (front+1)%CAPACITY; 
    
    
    }
    A
    Last edited by karumudi7; 11-28-2018 at 10:47 PM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    Err... is that really your code? You have two functions defined in main... which is weird to say the least, and I don't even remember if that's is valid C. Then even if it were valid, you didn't call them. Then you wrote:
    Code:
    send ( 2 args ) {
    and I'm like... why can't you just leave the function parameter list there? Is it so hard to give the actual code that you tested?

    Anyway, I'd guess that this:
    Code:
    msg = msgs[0];
    should have been
    Code:
    msg = msgs[front];
    Not certain though as I'm not going to rewrite your code to test it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Nov 2018
    Posts
    13
    I just figured that
    Code:
     msg = msgs[front] 


    Yes it is mine, it is having some unnecessary stuff and dont want to confuse.

    With that correction, I see first message is printing now but second message is coming blank.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,302
    Quote Originally Posted by karumudi7
    Yes it is mine, it is having some unnecessary stuff and dont want to confuse.
    Put aside your actual program and work on a program that just experiments with this idea of implementing a queue with an array using the dialect of C accepted by the micro controller. As it stands, your code already is confusing because it shouldn't even work.

    Quote Originally Posted by karumudi7
    With that correction, I see first message is printing now but second message is coming blank.
    Maybe because you forgot to actually receive the second message? That's what it looks like in the code that you posted.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Nov 2018
    Posts
    13

    Question

    Quote Originally Posted by laserlight View Post
    Put aside your actual program and work on a program that just experiments with this idea of implementing a queue with an array using the dialect of C accepted by the micro controller. As it stands, your code already is confusing because it shouldn't even work.


    Maybe because you forgot to actually receive the second message? That's what it looks like in the code that you posted.

    Here is the complete snippet. Sorry for confusion. I am trying to receive the second one, but nothing is coming.


    Code:
    
    
    
    //---------------- sender.c 
    
    
    int CAPACITY = 10;
    char* msgs[10];
    int size = 0;
    int rear = 9;
    int front = 0;
    
    
    syscall    sender(
          pid32        pid,        
          umsg32    msg        
        )
    {
        rear = (rear+1)%CAPACITY;
        size++;
        msgs[rear] = msg;
    
    
    return OK;
    }
    
    
    //--------------- receiver.c
    
    
    extern char* msgs[];
    extern int size;
    extern int rear;
    extern int front;
    extern int CAPACITY;
    
    
    umsg32    receiver(void)
    {
        msg = msgs[front];
        kprintf ("mssg2 %s",msgs[1] ); //debug
        front = (front+1)%CAPACITY;
        return msg;
    }
    
    //---------------- main.c
    
    extern char* msgs[];
    void sd(), rc();
    void main(void) {
    
    
        pid32 r1 = create(rc, 1024, 20, "receiver",0);
        pid32 s1 = create(sd, 1024, 20, "sender",2, r1, "HELLO!!!");
        pid32 s2 = create(sd, 1024, 20, "sender2",2, r1, "WORLD!!!");
        resume(s1);
        sleepms(3000);
        resume(s2);
        sleepms(3000);
        resume(r1);
        return OK;
    }
    
    
    void sd(pid32 pid, umsg32 msg) {
    
    
        sender(pid, msg);
        return OK;
    
    
    }
    
    
    void rc() {
    
    
    
    
        umsg32 mssg = receiver();
        kprintf("\n \n ---- Message recived: %s ----\n", mssg);
    
    
        umsg32 mssg2 = receiver();
        kprintf("\n \n ---- Message recived: %s ----\n", mssg2);
    
    
    
    
    }
    Output:
    Code:
    --- Message recived: Hello
    --- Message recived:
    Last edited by karumudi7; 11-28-2018 at 11:58 PM.

  14. #14
    Registered User
    Join Date
    May 2009
    Posts
    4,002
    From your post it looks like the exclamation point is a possible cause of a problem. Remove it and see if it works.

    Oops, you posted code that has nothing to do with the output!

    Goodbye.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  15. #15
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,616
    You can make 99% of it run on the host.
    Code:
    #include <stdio.h>
    
    // some portability hackery to make it run on host
    typedef int syscall;
    typedef char * umsg32;
    typedef int pid32;
    #define kprintf printf
    #define OK 0
    
    
    //---------------- sender.c
    
    
    int CAPACITY = 10;
    char* msgs[10];
    int size = 0;
    int rear = 9;
    int front = 0;
    
    
    syscall    sender(
          pid32        pid,
          umsg32    msg
        )
    {
        rear = (rear+1)%CAPACITY;
        size++;
        msgs[rear] = msg;
    
    
    return OK;
    }
    
    
    //--------------- receiver.c
    
    
    extern char* msgs[];
    extern int size;
    extern int rear;
    extern int front;
    extern int CAPACITY;
    
    
    umsg32    receiver(void)
    {
        umsg32 msg = msgs[front];       //!! Added type declaration
        kprintf ("mssg2 %s",msgs[front] ); //debug  !! fixed constant 1 to be variable front
        front = (front+1)%CAPACITY;
        return msg;
    }
    
    //---------------- main.c
    
    extern char* msgs[];
    void sd(pid32 pid, umsg32 msg), rc();
    int main(void) {
    
    #if 0
        pid32 r1 = create(rc, 1024, 20, "receiver",0);
        pid32 s1 = create(sd, 1024, 20, "sender",2, r1, "HELLO!!!");
        pid32 s2 = create(sd, 1024, 20, "sender2",2, r1, "WORLD!!!");
        resume(s1);
        sleepms(3000);
        resume(s2);
        sleepms(3000);
        resume(r1);
        return OK;
    #else
        sd(0,"HELLO!!!");
        sd(0,"WORLD!!!");
        rc();
    #endif
    }
    
    
    void sd(pid32 pid, umsg32 msg) {
    
    
        sender(pid, msg);
        //!! void functions do NOT return OK;
    
    
    }
    
    
    void rc() {
    
    
    
    
        umsg32 mssg = receiver();
        kprintf("\n \n ---- Message recived: %s ----\n", mssg);
    
    
        umsg32 mssg2 = receiver();
        kprintf("\n \n ---- Message recived: %s ----\n", mssg2);
    
    
    
    
    }
    Result
    Code:
    $ gcc foo.c
    $ ./a.out 
    mssg2 HELLO!!!
     
     ---- Message recived: HELLO!!! ----
    mssg2 WORLD!!!
     
     ---- Message recived: WORLD!!! ----
    I notice
    - your receiver doesn't decrement size.
    - your receiver doesn't check to see if a message is available
    - your sender doesn't check to see if there is space for a message.
    - your queue assumes the pointer remains valid forever.

    This last point means that code like this will NOT work.
    Code:
    void foo ( ) {
        char msg[20];
        for ( int i = 0 ; i <5 ; i++ ) {
            sprintf("Hey %d", i );
            sender(0,msg);
        }
    }
    It won't work in the first instance because all the messages point to the same array, which is being overwritten each time in the loop.

    It won't work in the second instance, because the array itself is only temporary, and goes out of scope when the function returns.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C Program to implement queue operations using linear queue
    By riteshkrjain in forum C Programming
    Replies: 2
    Last Post: 10-03-2017, 10:57 AM
  2. compiler keeps giving undefined reference errors
    By ecsx00 in forum C Programming
    Replies: 1
    Last Post: 11-24-2011, 03:12 AM

Tags for this Thread