static function buffers

G

g3rc4n

what is the best way to have a buffer in a function, for a (real)
example say a member function

std::string read(int offset, int nbytes){
static const char buffer_size(1024);
static char buffer[buffer_size];

::pread(file_desc,buffer,buffer_size,nbytes,offset);

return(std::string(buffer));
}

over pushing it on the stack or dynamically allocating it
 
S

something_fit

what is the best way to have a buffer in a function, for a (real)
example say a member function

std::string read(int offset, int nbytes){
    static const char buffer_size(1024);
    static char buffer[buffer_size];

    ::pread(file_desc,buffer,buffer_size,nbytes,offset);

    return(std::string(buffer));

}

over pushing it on the stack or dynamically allocating it

i meant static const int buffer_size(1024)
 
A

Alf P. Steinbach

* (e-mail address removed):
what is the best way to have a buffer in a function, for a (real)
example say a member function

std::string read(int offset, int nbytes){
static const char buffer_size(1024);

On most systems a 'char' is not able to hold the value 1024.

You should use 'ptrdiff_t', or to be conform but impractical, 'size_t'.

static char buffer[buffer_size];

::pread(file_desc,buffer,buffer_size,nbytes,offset);

return(std::string(buffer));

You can't do that unless the data in buffer is zero-terminated.
}

over pushing it on the stack or dynamically allocating it

It depends on how much stack space you have, and whether the routine needs to be
re-entrant for threading.

For typical desktop programming you have a few MiB stack space by default, so a
buffer of 1 KiB is nothing, hence the threading issue doesn't even pop up: for
that general case make that buffer an automatic variable (i.e. on the stack).

In the concrete case above, however, it's just silly to have a buffer at all
since you proceed to immediately create a std::string. In practice (with all
known compilers) std::string allocates a contiguous buffer, and in C++0x that is
guaranteed. So assuming 'pread' returns the number of bytes read, off the cuff,

std::string result( nbytes, '\0' );
result.resize( ::pread( file_desc, &result[0], nbytes, offset ) );
return result;


Cheers & hth.,

- Alf
 
S

something_fit

what is the best way to have a buffer in a function, for a (real)
example say a member function
std::string read(int offset, int nbytes){
    static const char buffer_size(1024);
    static char buffer[buffer_size];
    ::pread(file_desc,buffer,buffer_size,nbytes,offset);
    return(std::string(buffer));

over pushing it on the stack or dynamically allocating it

i meant static const int buffer_size(1024)

think you got a little side tracked, i don't care about the typos in
the function i just wanted to discuss static buffers i know in this
trivial case i can do without them

anyway so your saying it doesn't matter with that size, is there any a
time a buffer should be static?
 
A

Alan Woodland

something_fit said:
what is the best way to have a buffer in a function, for a (real)
example say a member function
std::string read(int offset, int nbytes){
static const char buffer_size(1024);
static char buffer[buffer_size];
::pread(file_desc,buffer,buffer_size,nbytes,offset);
return(std::string(buffer));
}
over pushing it on the stack or dynamically allocating it
i meant static const int buffer_size(1024)

think you got a little side tracked, i don't care about the typos in
the function i just wanted to discuss static buffers i know in this
trivial case i can do without them

anyway so your saying it doesn't matter with that size, is there any a
time a buffer should be static?
I've used things like this in cases where I'm using objects with
non-trivial constructors to manage the 'buffer' (which is really not
just a chunk of memory) and profiling shows that creating/destroying
them is taking a lot of time.

Actually in that case though it was in heavily threaded-code and I used
a 3rd party library that promised me thread-local storage to ensure the
function remained reentrant too.

Really I'd treat it as an optimisation, so the usual rules apply -
profile it and see if it's even hurting you at all!

Alan
 
J

Juha Nieminen

what is the best way to have a buffer in a function, for a (real)
example say a member function

std::string read(int offset, int nbytes){
static const char buffer_size(1024);
static char buffer[buffer_size];

::pread(file_desc,buffer,buffer_size,nbytes,offset);

return(std::string(buffer));
}

over pushing it on the stack or dynamically allocating it

One of the problems with a static buffer like that is that your
function is not thread-safe: If two threads call the function at the
same time (even if it happens on a 1-core system), it will break.

(If the function happened to be recursive, it might also break,
although that's most probably not the case here.)

There's really no need to use static arrays inside a function, unless
you really need for it to preserve its contents between function calls.
Using a stack-allocated local array is very fast (much faster than a
dynamically allocated one). There's usually no significant speed
difference over a static array.

The advantage of a stack-allocated array is that your function will be
completely thread-safe (at least as far as the array itself is concerned).
 
S

something_fit

thanks for replies, i can see there can be advantages but i'm sure i'd
be better off without them

cheers ;)
 
J

James Kanze

* (e-mail address removed):
On most systems a 'char' is not able to hold the value 1024.
You should use 'ptrdiff_t', or to be conform but impractical,
'size_t'.

Or just int. There's no reason here for anything special, and
int is the usual type, which should be used whenever there's no
reason to use something else. (Note that if he used the constant
directly, 1024 is an int. I don't see any reason to make it
anything else just because I'm giving it a name here.)
static char buffer[buffer_size];
::pread(file_desc,buffer,buffer_size,nbytes,offset);
return(std::string(buffer));
You can't do that unless the data in buffer is zero-terminated.

And of course, he should check that pread succeeded first. (If
the pread here is the one from Posix, it returns the length
actually read if it succeeds. And conveniently, there's a
constructor for std::string which takes the address and the
length, which is doubtlessly what he should use.
It depends on how much stack space you have, and whether the
routine needs to be re-entrant for threading.
For typical desktop programming you have a few MiB stack space
by default, so a buffer of 1 KiB is nothing, hence the
threading issue doesn't even pop up: for that general case
make that buffer an automatic variable (i.e. on the stack).
In the concrete case above, however, it's just silly to have a
buffer at all since you proceed to immediately create a
std::string. In practice (with all known compilers)
std::string allocates a contiguous buffer, and in C++0x that
is guaranteed. So assuming 'pread' returns the number of bytes
read, off the cuff,
std::string result( nbytes, '\0' );
result.resize( ::pread( file_desc, &result[0], nbytes, offset ) );
return result;

Excellent idea. Except that I think you still have to split the
::pread out and check for success first. (Again, if it is the
pread from Posix, it returns -1 in case of error. Which gets
converted to an unsigned size_t, the value of which will will
result in one hell of a big string; probably big enough to
result in bad_alloc or length_error. Neither of which are
really indicative of the actual error encountered.)
 
A

Alf P. Steinbach

* James Kanze:
In the concrete case above, however, it's just silly to have a
buffer at all since you proceed to immediately create a
std::string. In practice (with all known compilers)
std::string allocates a contiguous buffer, and in C++0x that
is guaranteed. So assuming 'pread' returns the number of bytes
read, off the cuff,
std::string result( nbytes, '\0' );
result.resize( ::pread( file_desc, &result[0], nbytes, offset ) );
return result;

Excellent idea. Except that I think you still have to split the
::pread out and check for success first. (Again, if it is the
pread from Posix, it returns -1 in case of error. Which gets
converted to an unsigned size_t, the value of which will will
result in one hell of a big string; probably big enough to
result in bad_alloc or length_error. Neither of which are
really indicative of the actual error encountered.)

Yes, but that's a different aspect than the thread's question.

There are many such unrelated aspects that could be commented on.


Cheers,

- Alf
 

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

Similar Threads

C pipe 1
fstream Buffers 26
Possible buffer overruns? 3
Lexical Analysis on C++ 1
How to manage static buffers 2
Strict aliasing and buffer handling 20
formatting buffers 3
Weird Behavior with Rays in C and OpenGL 4

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top