C software achitecture

J

joel.winteregg

hi all,

I'm a newbie in C programming (i'm coming from Java world "nobody is
perfect") and i have a question about possibilities in C software
architecture.

I saw that C functions where often using the return value to give
informations about execution of the function (0 = exec OK, 1 = exec
mistake). I'm wondering how i can do the cleanest code to put a command
result (like the "ls" Linux command) in a buffer. The code below show a
possible way of the function header:

//function executing a command (command) and putting the result in
buf
int exec(char* command, char** buf){
...
}

Here, the programmer (the user of this function) will need to give a
char** to get a char pointer back. So, he will need to create a pointer
and give it to the function (like this):

char* myBufPointer;
exec("ls -l", &myBufPointer);

The exec function will allocate a memory buffer (malloc) and the
programmer will need to free it afterwards... I don't know if it's a
really good idea to allocate memory in a function and to let the
programmer free it later ??

The other problem is coming from the way the programmer is creating the
buffer for the function. If he gonna do a static buffer (char
myBuf[200]) the function will not have to allocate memory... If the 200
char are not enough for the result (buf) how could i do ? Should i
check in the function if the buffer is static (if the pointer is
pointing to a memory area or not) and if the memory area is big enough
?? If it's a static buffer how can i extend it ? should i create an
other one ?

Is there an other way (a cleanest one) to create my function exec ??

Thanks a lot for your help and hope to read you soon...

Joël.W
 
P

pete

hi all,

I'm a newbie in C programming (i'm coming from Java world "nobody is
perfect") and i have a question about possibilities in C software
architecture.

I saw that C functions where often using the return value to give
informations about execution of the function (0 = exec OK, 1 = exec
mistake). I'm wondering how i can do the cleanest code to put a command
result (like the "ls" Linux command) in a buffer. The code below show a
possible way of the function header:

//function executing a command (command) and putting the result in
buf
int exec(char* command, char** buf){
...
}

Here, the programmer (the user of this function) will need to give a
char** to get a char pointer back. So, he will need to create a pointer
and give it to the function (like this):

char* myBufPointer;
exec("ls -l", &myBufPointer);

The exec function will allocate a memory buffer (malloc) and the
programmer will need to free it afterwards... I don't know if it's a
really good idea to allocate memory in a function and to let the
programmer free it later ??

The other problem is coming from the way the
programmer is creating the
buffer for the function. If he gonna do a static buffer (char
myBuf[200]) the function will not have to allocate memory...
If the 200
char are not enough for the result (buf) how could i do ? Should i
check in the function if the buffer is static (if the pointer is
pointing to a memory area or not) and if the memory area is big enough
?? If it's a static buffer how can i extend it ? should i create an
other one ?

Is there an other way (a cleanest one) to create my function exec ??

int exec(char* command, char* buf);

Make buf a char* instead of a char**,
and let the calling function handle allocation for the array,
as well as any freeing that may need to be done.
That way, the memory that buf points to,
could be either automatic, static or allocated.

char myBufPointer[200];
exec("ls -l", myBufPointer);

or

char *myBufPointer = malloc(200);
if (myBufPointer != NULL) {
exec("ls -l", myBufPointer);
}
free(myBufPointer);
 
R

Roger Leigh

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I saw that C functions where often using the return value to give
informations about execution of the function (0 = exec OK, 1 = exec
mistake). I'm wondering how i can do the cleanest code to put a command
result (like the "ls" Linux command) in a buffer. The code below show a
possible way of the function header:

int exec(char* command, char** buf)

exec is already a taken name (for POSIX; man 3 exec). I would
personally have written something like

int read_output(char **buffer, size_t *size,
const char *path, const char *arg, ...)
Here, the programmer (the user of this function) will need to give a
char** to get a char pointer back.

How will he know the buffer size? It's easiest to allocate it on the
fly and hand it back with the final size.

You'll need to look at fork(2), execve(2), exec(3), pipe(2), dup2(2),
wait(2) and read(2) in order to read output from a child process (and
probably fcntl(2) as well). This is not standard C. Ask on
comp.unix.programmer or comp.os.linux.development.apps for that.
There's no way (in Standard C) to read the standard output of a child
process from the parent. With POSIX, you can use a pipe:


parent child

1 - stdin 1 - stdin
2 - stdout +-- 2 - pipe[1]
3 - stderr | 3 - stderr
4 - pipe[0] <-+


Regards,
Roger

- --
Roger Leigh
Printing on GNU/Linux? http://gimp-print.sourceforge.net/
Debian GNU/Linux http://www.debian.org/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>

iD8DBQFCuzoBVcFcaSW/uEgRAmzyAKC18RYOjfJUQcLRZVLDGBRkg/GuGACcCDft
GNjOIuoCaSY+d0HvgN85saU=
=IqQU
-----END PGP SIGNATURE-----
 
G

Gordon Burditt

I saw that C functions where often using the return value to give
informations about execution of the function (0 = exec OK, 1 = exec
mistake). I'm wondering how i can do the cleanest code to put a command
result (like the "ls" Linux command) in a buffer. The code below show a
possible way of the function header:

//function executing a command (command) and putting the result in
buf
int exec(char* command, char** buf){
...
}

Here, the programmer (the user of this function) will need to give a
char** to get a char pointer back. So, he will need to create a pointer
and give it to the function (like this):

char* myBufPointer;
exec("ls -l", &myBufPointer);

The exec function will allocate a memory buffer (malloc) and the
programmer will need to free it afterwards... I don't know if it's a
really good idea to allocate memory in a function and to let the
programmer free it later ??

Some people don't like it, but it's a very common thing. Sometimes
you have a pair of functions: one allocates something, and one
deallocates it. In C++ this is called "constructors" and "destructors".
Often the functions (e.g. fopen() and fclose()) know more about how
much memory to allocate than the caller. What is allocated might not
be a simple memory block: it might be a whole linked list, or a structure
with pointers to some buffers, or whatever. The constructors and
destructors know that detail, the caller shouldn't.
The other problem is coming from the way the programmer is creating the
buffer for the function.

If you are passing in a char** so the function can return a pointer
to the allocated buffer, it's up to the function to allocate it.
If he gonna do a static buffer (char
myBuf[200]) the function will not have to allocate memory... If the 200
char are not enough for the result (buf) how could i do ?

If the caller allocates the buffer, the caller needs to pass in the
length of the buffer also (and CORRECTLY). The called function
CANNOT check this.
Should i
check in the function if the buffer is static (if the pointer is

You cannot check if a pointer points at a static buffer.
Don't even think about trying.
pointing to a memory area or not) and if the memory area is big enough
??
If it's a static buffer how can i extend it ?

You DON'T, so don't even think about trying.
should i create an
other one ?

My suggestion is to let the called exec() function do the allocating,
as it knows how much data it got back from the command it ran. Allocate
a reasonable guess. If you need more realloc() the buffer bigger.
Repeat if necessary.
Is there an other way (a cleanest one) to create my function exec ??

Beware that exec() is a common system function, and your exec()
function is likely to call functions (e.g. popen()) that call that
common system function. This isn't supposed to matter, but if the
library is broken it might.

Gordon L. Burditt
 
H

hatman

Thanks for your suggestion,

But the problem with the way you suggest to do it, comes from the size
of the command execution result. If the result is bigger than the
buffer, i will lost informations... As Gordon Burditt said, i sould
give the buffer size to the function ..?! And should i return an error
value (return 1;) if the buffer size isn't big enough ??
 
H

hatman

Thanks a lot for your suggestions Gordon,

I did more C++ than C and for sure i really like the way to allocate
with constructor and desallocate with destructor !! But the way to pair
functions will need documentions for users of the functions... I would
like to have the less documentation (my dream) !!
As you and pete said (second Post), i should give the buffer size to
the function, if it's 0, the function will allocate memory and if the
size is big enough, the function will put the result in it ... BUT, if
the buffer isn't big enough... The function can only reallocate dynamic
memory (not a static buffer..) ! So the function should try to
reallocate memory and if it doesn't work (= static buffer), return an
error code (return = 1;) ??

Is it the best way without doing a pair of functions ?

Thanks a lot for your help,

Joël.W
 
H

hatman

Jus an other question... if i give a function parameter as char** does
it normally mean that the function will allocate memory for it ?? cause
the function will have the possibility to "move" the char* !!

Or this way is also totaly correct ?

int exec(char* command, char** buf){
...
}

//buffer for 50 char
char* myBufPointer = (char*) malloc(51 * sizeof(char));
exec("ls -l", &myBufPointer);

Thanks for your suggestions ...

Joël.W
 
L

Lawrence Kirby

Jus an other question... if i give a function parameter as char** does
it normally mean that the function will allocate memory for it ?? cause
the function will have the possibility to "move" the char* !!

It could do, but you shouldn't assume this just because you see a char **
parameter type. strtol() is a standard library function that takes a char
** argument but doesn't allocat memory, it simply uses it as a method to
return a char * value.
Or this way is also totaly correct ?

int exec(char* command, char** buf){
...
}

//buffer for 50 char
char* myBufPointer = (char*) malloc(51 * sizeof(char));
exec("ls -l", &myBufPointer);

exec() doesn't know how large the buffer you are allocating is, so it
can't tell if and when it would need to extend it.

Lawrence
 
D

Default User

hatman said:
Thanks a lot for your suggestions Gordon,



Please quote a relevant portion of the previous message when replying.
To do so from the Google interface, don't use the Reply at the bottom
of the message. Instead, click "show options" and use the Reply shown
in the expanded headers.



Brian
 
G

Gordon Burditt

I did more C++ than C and for sure i really like the way to allocate
with constructor and desallocate with destructor !! But the way to pair
functions will need documentions for users of the functions... I would
like to have the less documentation (my dream) !!

You still need documentation (what are the args and in what
order and what do they mean?). And you still have the problem
that the caller cannot know whether a terabyte buffer will be big
enough. This, I think, is a much bigger problem than "you must
free this memory when you are done with it".
As you and pete said (second Post), i should give the buffer size to
the function, if it's 0, the function will allocate memory and if the
size is big enough, the function will put the result in it ... BUT, if
the buffer isn't big enough... The function can only reallocate dynamic
memory (not a static buffer..) ! So the function should try to
reallocate memory and if it doesn't work (= static buffer), return an
error code (return = 1;) ??

No, the function MUST NOT try to reallocate memory that might
be a static buffer. That way lies smegmentation violations.
Is it the best way without doing a pair of functions ?

If the second (destructor) function bothers you, in this case it's
easy. If you passed &buffer to the function and had it allocate
the buffer for you, the caller should call free(buffer) when it's
done with the data. But you still have to document the need to
free it.

Gordon L. Burditt
 
H

hatman

exec is already a taken name (for POSIX; man 3 exec). I would
personally have written something like

int read_output(char **buffer, size_t *size,
const char *path, const char *arg, ...)

The exec name was just an exemple for the forum... I didn't use this
one !! thanks for the advise...


How will he know the buffer size? It's easiest to allocate it on the
fly and hand it back with the final size.

But if the read_output function allocate it on the fly (in the
function), the user of the function will have to free the memory
afterwards (in his software)... Isn't it a bad idea (it will need
documentation !!)

You'll need to look at fork(2), execve(2), exec(3), pipe(2), dup2(2),
wait(2) and read(2) in order to read output from a child process (and
probably fcntl(2) as well). This is not standard C. Ask on
comp.unix.programmer or comp.os.linux.development.apps for that.
There's no way (in Standard C) to read the standard output of a child
process from the parent. With POSIX, you can use a pipe:

Thanks for the advise, but i found on Linux that the popen function was
calling a shell and piping the result in a buffer pointed by a FILE* !!
(But for me, the easiest way, was to execute all commands as:
"<myCommand> > file" and read the file afterwards !!

Thanks for your help ...

Joël.W
 
P

pete

hatman wrote:
But if the read_output function allocate it on the fly (in the
function), the user of the function will have to free the memory
afterwards (in his software)... Isn't it a bad idea (it will need
documentation !!)

Some functions are done that way.

How is the memory requirement determined?
Is it by simple calculation or by trial and error?
If it's a simple calculation,
you can pass in a buffer and the size of the buffer,
and if it's big enough, you can return zero,
and if it's not big enough, you can return the required size.

If your function is only able to determine whether or
not the buffer size is big enough,
without being able to determine the required size,
then you may be stuck with internal allocation.
 
H

hatman

Some functions are done that way.
How is the memory requirement determined?
Is it by simple calculation or by trial and error?
If it's a simple calculation,
you can pass in a buffer and the size of the buffer,
and if it's big enough, you can return zero,
and if it's not big enough, you can return the required size.

Ahhhhh yes, that's a really good idea !! and if the user of the
function give 0 as the buffer size, the function can allocate memory
for the data ...?!

Thanks for your help,

Joël.W
 
P

pete

hatman said:
Ahhhhh yes, that's a really good idea !! and if the user of the
function give 0 as the buffer size,
the function can allocate memory for the data ...?!

Then the *calling* (user) function
can allocate memory for the data, and call again.

size_t func(char* command, char *buf, sizt_t size);

size_t size;

size = func(command, ptr, 0);
ptr = malloc(size);
if (ptr != NULL) {
func(command, ptr, size);
}

or
size_t size;
char buf[20];
char *ptr;

size = func(command, buf, 20);
if (size != 0) {
ptr = malloc(size);
if (ptr != NULL) {
func(command, ptr, size);
} else {
/**/
}
/**/
free(ptr);
}
 
H

hatman

size_t func(char* command, char *buf, sizt_t size);
size_t size;

size = func(command, ptr, 0);
ptr = malloc(size);
if (ptr != NULL) {
func(command, ptr, size);
}

or
size_t size;
char buf[20];
char *ptr;

size = func(command, buf, 20);
if (size != 0) {
ptr = malloc(size);
if (ptr != NULL) {
func(command, ptr, size);
} else {
/**/
}
/**/
free(ptr);
}

Can i also do it like this: In the func function, if the size (passed
to the function) is 0 (as your first exemple), the func function will
allocate the memory ...?! In this case do i need to give a char** buf
to the function ?

Thanks for this "live" online help,

Joël.W
 
R

Roger Leigh

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

hatman said:
But if the read_output function allocate it on the fly (in the
function), the user of the function will have to free the memory
afterwards (in his software)... Isn't it a bad idea (it will need
documentation !!)

Of course. You should document that the caller is responsible for
freeing the memory. It's fairly common practice.
Thanks for the advise, but i found on Linux that the popen function was
calling a shell and piping the result in a buffer pointed by a FILE* !!

That's correct. popen is not the right tool for the job. If you
write a popen equivalent that works the other way around (that's what
those calls can be used to do), you can achieve this:

pipe() creates a pipe, and after you fork(), you use dup2() in the
child to replace stdout (fd 2) with the writing end of the pipe. When
the child is running, the parent can then read() everything sent to
stdout at the reading end of the pipe, and add it to a
dynamically-allocated buffer. This is the platform-specific [POSIX]
stuff you need to ask elsewhere about.
(But for me, the easiest way, was to execute all commands as:
"<myCommand> > file" and read the file afterwards !!

That also works. It just depends if you are OK creating temporary
files. If you read from the parent, you avoid this. If you are happy
with this, there's no need to get more complicated!


Regards,
Roger

- --
Roger Leigh
Printing on GNU/Linux? http://gimp-print.sourceforge.net/
Debian GNU/Linux http://www.debian.org/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>

iD8DBQFCvZG0VcFcaSW/uEgRAj8kAKCqcWx2opjr5BSRtlI48TmgNnwPDgCggY6H
sVwSLJzIc/INTAqus7lI2Bg=
=UID6
-----END PGP SIGNATURE-----
 
P

pete

hatman wrote:
Can i also do it like this: In the func function, if the size (passed
to the function) is 0 (as your first exemple), the func function will
allocate the memory ...?!

You could, but I wouldn't.
size = func(strings[2], NULL, 0);
ptr = malloc(size);
In this case do i need to give a char** buf
to the function ?

I'm recommending a (char *) instead of a (char **).

/* BEGIN new.c */

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

#define NELEM(A) (sizeof(A) / sizeof*(A))

size_t func(char* command, char *buf, size_t size);

int main(void)
{
char buf[20];
char *ptr;
char *strings[] = {
"Here's a string.",
"Here's a longer string.",
"Here's a much longer string."
};
size_t index;
size_t size;

for (index = 0; index != NELEM(strings); ++index) {
size = func(strings[index], buf, sizeof buf);
if (size == 0) {
puts(buf);
} else {
ptr = malloc(size);
if (ptr != NULL) {
func(strings[index], ptr, size);
puts(ptr);
free(ptr);
}
}
}
putchar('\n');
size = func(strings[2], NULL, 0);
ptr = malloc(size);
if (ptr != NULL) {
func(strings[2], ptr, size);
puts(ptr);
free(ptr);
}
return 0;
}

size_t func(char *command, char *buf, size_t size)
{
size_t length;

length = strlen(command);
if (size > length) {
strcpy(buf, command);
length = (size_t)-1;
}
return length + 1;
}

/* END new.c */
 
H

hatman

Thanks a lot for your help,
You could, but I wouldn't.

Could you maybe explain me why you wouldn't do it like this ? I think
the only problem, will come from a 0 size static buffer... (the
function won't be able to allocate memory for it!!)
I'm recommending a (char *) instead of a (char **).

the char* is ok if i only do memory allocation out of the function !?
if i also start doing it in the function i will need to use a char** to
give back the pointer of the new memory area ? Is that right ?

Thanks !!

Joël.W
 
P

pete

hatman said:
the char* is ok if i only do memory allocation out of the function !?
if i also start doing it in the
function i will need to use a char** to
give back the pointer of the new memory area ? Is that right ?

If func is never going to allocate memory, then this:

size_t func(char* command, char *buf, size_t size);

is workable.


If there are going to be options about whether
or not func() is going to allocate memory,
then a (char **) might be best.

size_t func(char* command, char **buf, size_t size);

In that case, you would have to work out some way for
the calling function to know whether or not
func() tried to allocate memory and whether or not
it was successful.


If func() is always going to allocate memory,
then it's best for func to return a pointer
and not take one as as argument.

char *func(char* command);

func would return either NULL, if allocation was unsuccessful,
or a pointer to memory.
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top