A question on C structures

Discussion in 'C Programming' started by nishant, Jul 20, 2004.

  1. nishant

    nishant Guest

    I've a structure:
    struct msghdr
    {
    //some goes here

    struct iovec *msg_iov;

    //some more ---
    }

    struct msghdr msg;


    The body of struct iovec looks like this:
    struct iovec
    {
    void *iov_base; // to point to a (char *) buffer
    int iov_len;
    }


    I declare a struct iovec array:
    struct iovec iov[10];

    Then fill it with values after proper memory allocation:

    for i: 0 to 9
    strcpy(iov.iov_base, buf);
    iov.iov_len = length;

    Then i make *msg_iov to point to this array:
    msg.msg_iov = iov;

    my question is when i try to access iov_base by:
    msg.msg_iov.iov_base
    it works only for i=0, for the rest it shows NULL.

    Now the interesting part, when i pass the
    address of 'msg' to a display function (display(struct msghdr *msg))
    then in that function i'm able to access the buffers without any problem
    using,
    msg->msg_iov.iov_base


    Isn't this weird?
    Why will a 'access method' make any difference
    Any suggestion/clarifications are welcome.
    nishant, Jul 20, 2004
    #1
    1. Advertising

  2. nishant a couché sur son écran :
    > struct msghdr
    > {
    > struct iovec *msg_iov;
    > }
    >
    > struct msghdr msg;
    >
    > struct iovec
    > {
    > void *iov_base; // to point to a (char *) buffer
    > int iov_len;
    > }
    >
    > my question is when i try to access iov_base by:
    > msg.msg_iov.iov_base
    > it works only for i=0, for the rest it shows NULL.
    >
    > Now the interesting part, when i pass the
    > address of 'msg' to a display function (display(struct msghdr *msg))
    > then in that function i'm able to access the buffers without any problem
    > using,
    > msg->msg_iov.iov_base
    >
    > Isn't this weird?


    No, it's not.

    > Why will a 'access method' make any difference
    > Any suggestion/clarifications are welcome.


    Because you passed the address of the structure (Which is The Good Way)
    via a pointer. The access is now 'indirect'. For clarification, I
    suggest that you change your definition for

    display (struct msghdr *p_msg)
    {
    <...>
    p_msg->msg_iov.iov_base
    }

    or (probably better, at last to me)

    display (struct msghdr *this)
    {
    <...>
    this->msg_iov.iov_base
    }

    --


    Emmanuel
    Emmanuel Delahaye, Jul 20, 2004
    #2
    1. Advertising

  3. On 19 Jul 2004 21:54:56 -0700, (nishant) wrote:

    snip disjointed code fragments

    >my question is when i try to access iov_base by:
    >msg.msg_iov.iov_base
    >it works only for i=0, for the rest it shows NULL.
    >
    >Now the interesting part, when i pass the
    >address of 'msg' to a display function (display(struct msghdr *msg))
    >then in that function i'm able to access the buffers without any problem
    >using,
    >msg->msg_iov.iov_base
    >
    >
    >Isn't this weird?
    >Why will a 'access method' make any difference
    >Any suggestion/clarifications are welcome.


    You need to post a compilable example that illustrates the behavior
    you describe.


    <<Remove the del for email>>
    Barry Schwarz, Jul 20, 2004
    #3
  4. nishant

    Al Bowers Guest

    nishant wrote:
    > I've a structure:
    > struct msghdr
    > {
    > //some goes here
    >
    > struct iovec *msg_iov;
    >
    > //some more ---
    > }
    >
    > struct msghdr msg;
    >
    >
    > The body of struct iovec looks like this:
    > struct iovec
    > {
    > void *iov_base; // to point to a (char *) buffer
    > int iov_len;
    > }
    >
    >
    > I declare a struct iovec array:
    > struct iovec iov[10];
    >
    > Then fill it with values after proper memory allocation:
    >
    > for i: 0 to 9
    > strcpy(iov.iov_base, buf);
    > iov.iov_len = length;
    >
    > Then i make *msg_iov to point to this array:
    > msg.msg_iov = iov;
    >
    > my question is when i try to access iov_base by:
    > msg.msg_iov.iov_base
    > it works only for i=0, for the rest it shows NULL.


    This doen't seem right. Your syntax, msg.msg_iov.iov_base,
    looks fine. I am assuming that all 10 of the dynamic allocations
    were successful since the strcpy worked in the loop. There must
    be something else involved.

    See the example

    > Now the interesting part, when i pass the
    > address of 'msg' to a display function (display(struct msghdr *msg))
    > then in that function i'm able to access the buffers without any problem
    > using,
    > msg->msg_iov.iov_base
    >
    > Isn't this weird?

    Your use of the -> operator is correct. I guess your 'weird' comment
    is because the . operator is not working but the -> is working
    as expected. It appears to me that you are using the operators
    corrected.

    > Why will a 'access method' make any difference
    > Any suggestion/clarifications are welcome.


    The example:

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

    #define SZ 10

    struct iovec
    {
    void *iov_base; // to point to a (char *) buffer
    size_t iov_len;
    };

    struct msghdr
    {
    //some goes here

    struct iovec *msg_iov;

    //some more ---
    };

    void FreeMsghdr(struct msghdr *msg)
    {
    int i;

    for(i = 0; i < SZ; i++)
    {
    free(msg->msg_iov.iov_base);
    msg->msg_iov.iov_base = NULL;
    msg->msg_iov.iov_len = 0;
    }
    msg->msg_iov = NULL;
    return;
    }

    int main(void)
    {
    struct msghdr msg;
    struct iovec iov[SZ];
    int i;
    char buf[32];

    for(i = 0; i < SZ;i++)
    {
    iov.iov_base = malloc(32);
    if(iov.iov_base)
    {
    sprintf(buf,"HelloWorld_%d",i);
    strcpy(iov.iov_base,buf);
    iov.iov_len = strlen(buf);
    }
    }
    msg.msg_iov = iov;
    for(i = 0;i < SZ;i++)
    printf("msg.msg_iov[%d].iov_base = \"%s\"\n",i,
    msg.msg_iov.iov_base?msg.msg_iov.iov_base:"NULL");
    FreeMsghdr(&msg);
    puts("\nAfter Calling FreeMsghdr:");
    for(i = 0;i < SZ;i++)
    printf("iov[%d].iov_base = %s\t\t"
    "iov[%d].iov_len = %u\n",i,
    iov.iov_base?iov.iov_base:"NULL",
    i,iov.iov_len);
    return 0;
    }

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Jul 20, 2004
    #4
  5. nishant

    Xingbo G Guest

    In the function void FreeMsghdr(struct msghdr *msg), isn't it enough
    by calling free()? Why would we still need

    msg->msg_iov.iov_base = NULL;
    msg->msg_iov.iov_len = 0;

    and

    msg->msg_iov = NULL;

    I remember I saw this before but have no idea why we need them.


    Al Bowers <> wrote in message news:<>...
    > nishant wrote:
    > > I've a structure:
    > > struct msghdr


    [snip]

    >
    > The example:
    >
    > #include <stdio.h>
    > #include <string.h>
    > #include <stdlib.h>
    >
    > #define SZ 10
    >
    > struct iovec
    > {
    > void *iov_base; // to point to a (char *) buffer
    > size_t iov_len;
    > };
    >
    > struct msghdr
    > {
    > //some goes here
    >
    > struct iovec *msg_iov;
    >
    > //some more ---
    > };
    >
    > void FreeMsghdr(struct msghdr *msg)
    > {
    > int i;
    >
    > for(i = 0; i < SZ; i++)
    > {
    > free(msg->msg_iov.iov_base);
    > msg->msg_iov.iov_base = NULL;
    > msg->msg_iov.iov_len = 0;
    > }
    > msg->msg_iov = NULL;
    > return;
    > }
    >
    > int main(void)
    > {
    > struct msghdr msg;
    > struct iovec iov[SZ];
    > int i;
    > char buf[32];
    >
    > for(i = 0; i < SZ;i++)
    > {
    > iov.iov_base = malloc(32);
    > if(iov.iov_base)
    > {
    > sprintf(buf,"HelloWorld_%d",i);
    > strcpy(iov.iov_base,buf);
    > iov.iov_len = strlen(buf);
    > }
    > }
    > msg.msg_iov = iov;
    > for(i = 0;i < SZ;i++)
    > printf("msg.msg_iov[%d].iov_base = \"%s\"\n",i,
    > msg.msg_iov.iov_base?msg.msg_iov.iov_base:"NULL");
    > FreeMsghdr(&msg);
    > puts("\nAfter Calling FreeMsghdr:");
    > for(i = 0;i < SZ;i++)
    > printf("iov[%d].iov_base = %s\t\t"
    > "iov[%d].iov_len = %u\n",i,
    > iov.iov_base?iov.iov_base:"NULL",
    > i,iov.iov_len);
    > return 0;
    > }
    Xingbo G, Jul 21, 2004
    #5
  6. nishant

    nishant Guest

    salut Emmanuel
    i'm sorry if i made u couché (i hope my french is correct :) )
    Thank you for replying. but the question still remains ---

    Emmanuel Delahaye <> wrote in message news:<>...
    > nishant a couché sur son écran :
    > -----------
    > > Now the interesting part, when i pass the
    > > address of 'msg' to a display function (display(struct msghdr *msg))
    > > then in that function i'm able to access the buffers without any problem
    > > using,
    > > msg->msg_iov.iov_base
    > >
    > > Isn't this weird?

    >
    > No, it's not.
    >
    > > Why will a 'access method' make any difference
    > > Any suggestion/clarifications are welcome.

    >
    > Because you passed the address of the structure (Which is The Good Way)
    > via a pointer. The access is now 'indirect'. For clarification, I
    > suggest that you change your definition for
    >


    i will restate my question,
    A method whether 'direct' or 'indirect' shudn't make any difference
    when accessing a value, right?
    if i can access it thru a pointer then why not by the variable itself
    ??


    > display (struct msghdr *p_msg)
    > {
    > <...>
    > p_msg->msg_iov.iov_base
    > }
    >
    > or (probably better, at last to me)
    >
    > display (struct msghdr *this)
    > {
    > <...>
    > this->msg_iov.iov_base
    > }
    nishant, Jul 21, 2004
    #6
  7. nishant

    nishant Guest

    Hello Al
    Thank you for replying.
    But The question still remains

    >
    > > Now the interesting part, when i pass the
    > > address of 'msg' to a display function (display(struct msghdr *msg))
    > > then in that function i'm able to access the buffers without any problem
    > > using,
    > > msg->msg_iov.iov_base
    > >
    > > Isn't this weird?

    > Your use of the -> operator is correct. I guess your 'weird' comment
    > is because the . operator is not working but the -> is working
    > as expected.


    You are Right, Any explanantions for that ?
    I even tried cleaning up the memory first before assigning anything as
    you suggested. But even that doesn't work.
    nishant, Jul 21, 2004
    #7
  8. nishant

    Al Bowers Guest

    nishant wrote:
    > Hello Al
    > Thank you for replying.
    > But The question still remains
    >
    >
    >>>Now the interesting part, when i pass the
    >>>address of 'msg' to a display function (display(struct msghdr *msg))
    >>>then in that function i'm able to access the buffers without any problem
    >>>using,
    >>>msg->msg_iov.iov_base
    >>>
    >>>Isn't this weird?

    >>
    >>Your use of the -> operator is correct. I guess your 'weird' comment
    >>is because the . operator is not working but the -> is working
    >>as expected.

    >
    >
    > You are Right, Any explanantions for that ?
    > I even tried cleaning up the memory first before assigning anything as
    > you suggested. But even that doesn't work.


    From the info you have provided, I cannot give an explanation.

    You have:
    1. Provided the declarations and assignments for the structs.
    They seem fine.
    2. Shown that you have an understanding of the . operator and the
    -> operation and the their usage.

    Yet! The . operator is not working and the -> is working.

    This leaves me to believe that there is a suble error in the code
    that you have yet to uncover.

    I would suggest that you simply the code, still showing 'weird'
    behavior, to a form that would allow you to post it.


    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Jul 21, 2004
    #8
  9. nishant

    Al Bowers Guest

    Xingbo G wrote:

    > In the function void FreeMsghdr(struct msghdr *msg), isn't it enough
    > by calling free()? Why would we still need
    >
    > msg->msg_iov.iov_base = NULL;
    > msg->msg_iov.iov_len = 0;
    >
    > and
    >
    > msg->msg_iov = NULL;
    >


    It is not needed. It is not neccessary, especially in the trival
    example. It is more like a 'religion'.

    In the design of a function that frees dynamic memory in objects,
    some feel that it best not leave dangling pointers that could
    lead to problems in a complex, large code project. So, the pointers
    and other members of the struct are given a value that can asseverate
    the condition of the object elsewhere in the code.


    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Jul 21, 2004
    #9
  10. nishant

    nishant Guest

    Hi Al,
    I include the code below, if this is what u want.
    The program makes use of socket calls to accept a connection and then
    recieve some data. The 'weird' part is with the the " /*### "
    comments.
    I hope this time the 'weird'ness is clear to you.


    #include <stdio.h>
    #include <------->

    #define PORT 6000
    #define BUFNUM 3
    #define BUFLEN 20
    #define BACKLOG 15

    /* int recvmsg(int, struct msghdr, int)
    Description: It is used to receive an array of buffers (from the
    socket interface specified by int s)
    and copy it to struct msghdr *mesghdr */


    int recvmsg(int s, struct msghdr *mesghdr, int flags)
    {
    char *buf;
    int i,j, bufsize, fromlen;
    struct sockaddr_in from_addr;
    struct iovec iov[BUFNUM];

    fromlen = sizeof(struct sockaddr_in);
    buf = (char *)malloc(BUFLEN+1);
    bufsize = BUFLEN+1;

    for(j=0; j<BUFNUM; j++)
    {
    iov[j].iov_base = (char *)malloc(BUFLEN);
    iov[j].iov_len = BUFLEN;
    }

    for(j=0; j<BUFNUM; j++) // keep recieving BUFNUM times
    {
    i = recvfrom(s,buf,bufsize,flags,&from_addr,&fromlen); // a
    socket call
    strcpy(iov[j].iov_base, buf);
    iov[j].iov_len = bufsize;
    }

    mesghdr->msg_iov = iov;

    mesghdr->msg_name = (void *)&from_addr;
    mesghdr->msg_namelen = fromlen;
    mesghdr->msg_iovlen = BUFNUM;

    return (i);

    }

    void display(struct msghdr *msg) // takes the address of msghdr
    {
    int i;
    char recvdata[BUFNUM][BUFLEN];
    for(i=0; i<BUFNUM && strcmp(msg->msg_iov.iov_base,"") != 0;
    i++)
    {
    strcpy(recvdata, msg->msg_iov.iov_base); /* ###
    '->'works fine */
    printf("\nMessage Received %d: %s\n", i+1,
    recvdata);
    }
    }

    void main()
    {
    int new_fd, sockfd, i;
    int sockin_size;
    char recvdata[BUFNUM][BUFLEN];

    struct msghdr mesghdr;
    struct sockaddr_in local_addr, remote_addr;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
    printf("Sockfd error\n");
    exit(0);
    }

    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(PORT);
    local_addr.sin_addr.s_addr = INADDR_ANY;
    /*local_addr.sin_addr.s_addr = inet_addr("172.31.41.17");
    */

    memset(&(local_addr.sin_zero),'\0', 8); /* Required */

    if( bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct
    sockaddr)) == -1)
    {
    printf("BIND ERROR\n");
    exit(0);
    }

    if( listen(sockfd, BACKLOG) == -1)
    {
    printf("LISTEN ERROR\n");
    exit(0);
    }

    sockin_size = sizeof(struct sockaddr_in);
    printf("\n before accept \n");
    new_fd = accept(sockfd, (struct sockaddr *) &remote_addr,
    &sockin_size);
    printf("\n after accept \n");

    printf("server: got connection from
    %s\n",inet_ntoa(remote_addr.sin_addr));
    memset(mesghdr, 0, sizeof (struct msghdr));
    mesghdr.msg_name = (void *)malloc(sizeof(struct sockaddr));
    mesghdr.msg_namelen = sizeof(struct sockaddr);
    mesghdr.msg_iovlen = BUFNUM;

    if(( i = recvmsg(new_fd,(struct msghdr *)&mesghdr,0)) == -1 )
    {
    perror("recvmsg error: ");
    printf("Error No: %d\n", errno);
    exit(0);
    }

    /* for(i=0; i<BUFNUM && strcmp(mesghdr.msg_iov.iov_base," ")
    != 0; i++)
    {
    strcpy(recvdata, mesghdr.msg_iov.iov_base); /*### '.'doesn't
    work */
    printf("\nMessage Received %d: %s\n", i+1, recvdata);
    } */

    display((struct msghdr *)&mesghdr); // included this since the above
    doesn't work

    printf("\n");

    close(sockfd);
    }

    ********************* structure body ***************************


    struct msghdr
    {
    //some goes here

    struct iovec *msg_iov;

    //some more ---
    }msg;

    struct iovec
    {
    void *iov_base; // to point to a (char *) buffer
    int iov_len;
    }iov[10];
    nishant, Jul 22, 2004
    #10
  11. nishant

    Al Bowers Guest

    nishant wrote:

    There are a number of problem areas that I want memtion.
    However, here is one that I will address as a serious flaw.

    In the function recvmsg (definition below), you declare a struct
    object iov. This object is visible only within that function.

    > int recvmsg(int s, struct msghdr *mesghdr, int flags)
    > {
    > char *buf;
    > int i,j, bufsize, fromlen;
    > struct sockaddr_in from_addr;
    > struct iovec iov[BUFNUM];
    >
    > fromlen = sizeof(struct sockaddr_in);
    > buf = (char *)malloc(BUFLEN+1);
    > bufsize = BUFLEN+1;
    >
    > for(j=0; j<BUFNUM; j++)
    > {
    > iov[j].iov_base = (char *)malloc(BUFLEN);
    > iov[j].iov_len = BUFLEN;
    > }
    >
    > for(j=0; j<BUFNUM; j++) // keep recieving BUFNUM times
    > {
    > i = recvfrom(s,buf,bufsize,flags,&from_addr,&fromlen); // a
    > socket call
    > strcpy(iov[j].iov_base, buf);
    > iov[j].iov_len = bufsize;
    > }
    >
    > mesghdr->msg_iov = iov;


    Oops! You have assigned a member of an object declared in function
    main a value that will be meaningless once function recvfrom exits. iov
    ceases its existence at function exit.

    >
    > mesghdr->msg_name = (void *)&from_addr;
    > mesghdr->msg_namelen = fromlen;
    > mesghdr->msg_iovlen = BUFNUM;
    >
    > return (i);
    >
    > }
    >


    > void main()
    > {
    > int new_fd, sockfd, i;
    > int sockin_size;
    > char recvdata[BUFNUM][BUFLEN];
    >
    > struct msghdr mesghdr;
    > struct sockaddr_in local_addr, remote_addr;
    >



    ................snip...............

    >
    > if(( i = recvmsg(new_fd,(struct msghdr *)&mesghdr,0)) == -1 )
    > {
    > perror("recvmsg error: ");
    > printf("Error No: %d\n", errno);
    > exit(0);
    > }
    >
    > /* for(i=0; i<BUFNUM && strcmp(mesghdr.msg_iov.iov_base," ")
    > != 0; i++)
    > {
    > strcpy(recvdata, mesghdr.msg_iov.iov_base); /*### '.'doesn't
    > work */


    Since the value mesghdr.msg_iov represents a pointer to storage
    that may no longer exist, all bets are off and it is not surprising
    that it doesn't work.


    > printf("\nMessage Received %d: %s\n", i+1, recvdata);
    > } */
    >
    > display((struct msghdr *)&mesghdr); // included this since the above
    > doesn't work
    >
    > printf("\n");
    >
    > close(sockfd);
    > }
    >
    > ********************* structure body ***************************
    >
    >
    > struct msghdr
    > {
    > //some goes here
    >
    > struct iovec *msg_iov;
    >
    > //some more ---
    > }msg;


    This global struct object, msg, may be causing confusion.
    I do not see it being used in your code snippet.

    >
    > struct iovec
    > {
    > void *iov_base; // to point to a (char *) buffer
    > int iov_len;
    > }iov[10];


    Same here with iov.
    Get rid of both globals, msg and iov. Declare the struct objects
    in function main and redesign the functions to use these objects.

    --
    Al Bowers
    Tampa, Fl USA
    mailto: (remove the x to send email)
    http://www.geocities.com/abowers822/
    Al Bowers, Jul 22, 2004
    #11
  12. nishant

    nishant Guest

    Hello Al,
    Thanks a bunch.
    I got the mistake i was making.


    > > mesghdr->msg_iov = iov;

    >
    > Oops! You have assigned a member of an object declared in function
    > main a value that will be meaningless once function recvfrom exits. iov
    > ceases its existence at function exit.


    You hit the nail on the head !

    > > struct msghdr
    > > {
    > > //some goes here
    > >
    > > struct iovec *msg_iov;
    > >
    > > //some more ---
    > > }msg;

    >
    > This global struct object, msg, may be causing confusion.
    > I do not see it being used in your code snippet.
    >
    > >
    > > struct iovec
    > > {
    > > void *iov_base; // to point to a (char *) buffer
    > > int iov_len;
    > > }iov[10];

    >
    > Same here with iov.
    > Get rid of both globals, msg and iov. Declare the struct objects
    > in function main and redesign the functions to use these objects.



    well, these structs were just for ur reference. i'm not using them in the prog
    nishant, Jul 23, 2004
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. kazack

    Question about Structures

    kazack, Nov 11, 2003, in forum: C++
    Replies:
    1
    Views:
    396
    Karl Heinz Buchegger
    Nov 11, 2003
  2. Saikrishna

    Data Structures Question...

    Saikrishna, Apr 6, 2004, in forum: C++
    Replies:
    3
    Views:
    449
    Michael Mendelsohn
    Apr 8, 2004
  3. Generic Usenet Account

    RTTI Question: typeid() for structures

    Generic Usenet Account, Feb 18, 2005, in forum: C++
    Replies:
    2
    Views:
    2,513
  4. tweak
    Replies:
    14
    Views:
    2,761
    Eric Sosman
    Jun 11, 2004
  5. Alfonso Morra
    Replies:
    11
    Views:
    701
    Emmanuel Delahaye
    Sep 24, 2005
Loading...

Share This Page