How to find the size of dynamically allocated struct-type variable?

N

nmtoan

Hi,

I could not find any answer to this simple question of mine.

Suppose I have to write a program, the main parts of it are as follows:

#include <blahblah.h>

struct
{
double *my_dynamic_variable1;
int **my_dynamic_variable2;
char ***my_dynamic_variable3;
} gv;

main()
{
FILE *fbinary;
fbinary = fopen("test.bnr","wb");

ALLOCATE memory for gv.my_dynamic_vairable1, 2 and 3;

fwrite(gv,sizeof(gv),1,fbinary);
....
}

The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?
The same question raised when reading gv from a binary file. Is there
any alternative (but elegant way) of finding the size of gv, without
using sizeof?
 
M

Marc Boyer

Le 21-10-2005 said:
I could not find any answer to this simple question of mine.

Did you really have read a C book ?
Suppose I have to write a program, the main parts of it are as follows:

#include <blahblah.h>

struct
{
double *my_dynamic_variable1;
int **my_dynamic_variable2;
char ***my_dynamic_variable3;
} gv;

main()
{
FILE *fbinary;
fbinary = fopen("test.bnr","wb");

ALLOCATE memory for gv.my_dynamic_vairable1, 2 and 3;

fwrite(gv,sizeof(gv),1,fbinary);
....
}

The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?

Did you mean 'the size of variable gv' (known at compile time:
sizoeof(gv)), or 'the total size of allocated fields of gv' ?

Because there is no way to known the size dynamicaly allocated
except to keep it from the allocation instruction.


Marc Boyer
 
E

Emmanuel Delahaye

(e-mail address removed) a écrit :
The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?

It's your job to record the size of the allocated blocs. Here is a
common approach for a flexible array :

struct array_of_int
{
int *a;
size_t n;
};

and here is the generic version :

struct array
{
/* address of the first element */
void *arr;

/* size of an element */
size_t size;

/* number of elements */
size_t number;
};

of course, you provide the create/delete/access functions that hide the
gory details...
 
E

Emmanuel Delahaye

(e-mail address removed) a écrit :
The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?

It's your job to record the size of the allocated blocks. Here is a
common approach for a flexible array :

struct array_of_int
{
int *a;
size_t n;
};

and here is the generic version :

struct array
{
/* address of the first element */
void *arr;

/* size of an element */
size_t size;

/* number of elements */
size_t number;
};

of course, you provide the create/delete/access functions that hide the
gory details...
 
J

John Bode

Hi,

I could not find any answer to this simple question of mine.

Suppose I have to write a program, the main parts of it are as follows:

#include <blahblah.h>

struct
{
double *my_dynamic_variable1;
int **my_dynamic_variable2;
char ***my_dynamic_variable3;
} gv;

main()
{
FILE *fbinary;
fbinary = fopen("test.bnr","wb");

ALLOCATE memory for gv.my_dynamic_vairable1, 2 and 3;

fwrite(gv,sizeof(gv),1,fbinary);
....
}

The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?
The same question raised when reading gv from a binary file. Is there
any alternative (but elegant way) of finding the size of gv, without
using sizeof?

The thing is, the size of "gv" itself will not change as you allocate
memory: it will always be sized to hold three pointer values. The size
of the memory that the pointers point to is what's variable, and that's
something you have to keep track of manually as you allocate the
memory.

Secondly, the fwrite() call above won't do what you think it will. It
will write the contents of the struct, which is three pointer values.
It will not write the contents of what the pointers point to. Instead,
you will need to call fwrite separately on each member:

fwrite(gv.my_dynamic_variable1, sizeof *(gv.my_dynamic_variable1),
num_dv1_elements, binary);

/**
* Assumes memory for my_dynamic_variable2 is contiguous
*/
fwrite(gv.my_dynamic_variable2, sizeof **(gv.my_dynamic_variable2),
num_dv2_elements, binary);

etc.

I recommend you store the sizes as part of the struct, and create a
wrapper to abstract out the fwrite operations, like so:

struct gv {
double *my_dynamic_variable1;
size_t dv1size;

int **my_dynamic_variable2;
size_t dv2size_d0;
size_t dv2size_d1;

char ***my_dynamic_variable3;
size_t dv3size_d0;
size_t dv3size_d1;
size_t dv3size_d2;
} gv;

....

void write_gv(FILE *stream, struct gv gv)
{
/**
* Write the size of each array, followed by the array contents
*/
fwrite((void*) &gv.dv1size, sizeof gv.dv1size, 1, stream);
fwrite((void*) gv.my_dynamic_variable1, sizeof
*(gv.my_dynamic_variable1), gv.dv1size, stream);

fwrite((void*) &gv.dv2size_d0, sizeof gv.dv2size_d0, 1, stream);
fwrite((void*) &gv.dv2size_d1, sizeof gv.dv2size_d1, 1, stream);

/**
* If the array contents are contiguous, you can write the whole
* thing out in one call as below. If not, you'll have to write
* each row out separately in a loop.
*/
fwrite((void*) gv.my_dynamic_variable2, sizeof
*(gv.my_dynamic_variable2), gv.dv2size_d0 * gv.dv2size_d1, stream);

/**
* etc.
*/
}

DISCLAIMER: the above has not been tested, and I don't do binary I/O as
a rule, so there may be errors in the above. It should give you an
idea of what you need to do, however.
 
K

Keith Thompson

I could not find any answer to this simple question of mine.

Suppose I have to write a program, the main parts of it are as follows:

#include <blahblah.h>

struct
{
double *my_dynamic_variable1;
int **my_dynamic_variable2;
char ***my_dynamic_variable3;
} gv;

main()
{
FILE *fbinary;
fbinary = fopen("test.bnr","wb");

ALLOCATE memory for gv.my_dynamic_vairable1, 2 and 3;

fwrite(gv,sizeof(gv),1,fbinary);
....
}

The problem is that, since gv is dynamically allocated at run-time, and
gv contains various variable types, how can I correctly find the actual
size of the variable gv, in order to write it corerctly to the file?
The same question raised when reading gv from a binary file. Is there
any alternative (but elegant way) of finding the size of gv, without
using sizeof?

Presumably the line "ALLOCATE memory for ..." involves calls to
malloc(). The size of gv itself is fixed, and can be computed with
"sizeof gv", so presumably you want to know the size of the memory
you've allocated.

It seems obvious that, given

char *ptr;
ptr = malloc(1000); /* assume malloc() succeeds */

there should be some way to retrieve the allocated size, 1000, from
ptr. After all, the implementation has to know how much memory was
allocated so it can deallocate it when you call free(ptr).

But the C standard provides no such function.

Why not? For one thing, the actual allocated size might be more than
you asked for; for example, malloc(1000) might allocate a block of
1024 bytes. The implementation isn't required to keep track of both
1000 (the amount requested) and 1024 (the amount actually allocated).

Now if the standard had defined such a function, all the implementers
would provide it and I don't think anyone would complain about the
minor burden. But it doesn't, so if you want to know how many bytes
you allocated, you're on your own. You know how many bytes you
requested, so you just need to remember it.

Your fwrite() call writes the contents of the variable gv itself to
your file. That means you'll get 3 pointer values written to the
file, which is not a useful thing to do (the pointer values are
meaningless outside the current execution of your program).
Presumably you want to write the data that gv points to. Since gv
contains a pointer-to-double, a pointer-to-pointer-to-int, and a
pointer-to-pointer-to-pointer-to-char, we have no way of knowing what
kind of data structure is out there (arrays, linked lists, whatever).
You'll need to figure out just what data you want to write to the
file, and how you want to represent it so that it can be read back in
later. Anything involving pointers will have to be translated to some
other form.
 

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

Forum statistics

Threads
474,170
Messages
2,570,925
Members
47,464
Latest member
Bobbylenly

Latest Threads

Top