A question on C structures

N

nishant

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.
 
E

Emmanuel Delahaye

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
}
 
B

Barry Schwarz

On 19 Jul 2004 21:54:56 -0700, (e-mail address removed) (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>>
 
A

Al Bowers

nishant said:
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;
}
 
X

Xingbo G

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 said:
nishant said:
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;
}
 
N

nishant

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 said:
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
}
 
N

nishant

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.
 
A

Al Bowers

nishant said:
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.
 
A

Al Bowers

Xingbo said:
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.
 
N

nishant

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];
 
A

Al Bowers

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.
 
N

nishant

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

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top