Array typedef as function parameter

N

Noob

Hello everyone,

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

bar is supposed to call foo.

One (round-about) way would be to make a copy of the
contents of p2:

int bar(unsigned char *p2)
{
toto param;
memcpy(param, p2, sizeof param);
return foo(&param);
}

but what is the way to avoid the copy?
(i.e. pass "p2" directly to foo)

Regards.
 
B

Barry Schwarz

Hello everyone,

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);

The type of p1 is not pointer to unsigned char - char*. Since toto is
an alias for array of 16 char, the type of p1 is pointer to array of
16 unsigned char - unsigned char (*)[16].
int bar(unsigned char *p2);

bar is supposed to call foo.

Then it is bar's job to give foo an argument of the type it expects.
One (round-about) way would be to make a copy of the
contents of p2:

int bar(unsigned char *p2)
{
toto param;
memcpy(param, p2, sizeof param);
return foo(&param);
}

but what is the way to avoid the copy?
(i.e. pass "p2" directly to foo)

If p2 does in fact point to an array of at least 16 unsigned char,
then you could call foo with a simple cast, converting the value in p2
from unsigned char* to unsigned char(*)[16].

On the other hand, it is somewhat unusual for a function to expect a
pointer to array (as opposed to a pointer to first element of the
array). You might want to rethink the signature of foo. You don't
show the code but if foo wants to look at any of the characters
pointed to by p1, it has to use syntax similar to p1[0]. Unless
there is more than one toto in the area p1 points to, this introduces
a level of indirection that is just confusing.
 
T

Tim Rentsch

Noob said:
Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

Exceptions to the above rule still should avoid the use of
ordinary looking type names; make typedef names for array types
stand out in some way that makes it obvious they are unusual, eg,
'xyz_ARRAY'.

Never use type names that are typedefs for array types with
function parameters. (There are some Standard-defined types
which make it hard to follow this rule in some cases, but as
examples such things should be shunned, not imitated.)
bar is supposed to call foo.

[what is the way to] pass "p2" directly to foo?

If the typedef and declarations of foo() and bar() are completely
outside of your control, there basically isn't any choice other
than casting. That by itself should be a tip off that something
is wrong.

If those things are under your control, change them. The revised
code should (a) follow the advice given above, and (b) not do
any casting. Exactly what interface should be used for foo()
depends on what it is foo() is doing, but it should be possible
to choose a type and a declaration for its single parameter that
satisfies (a) and (b).
 
N

Noob

Tim said:
Noob said:
Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)
As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API.

Suppose int foo(unsigned char *param);

I'd get a mix of these:

A) unsigned char *p; foo(p);
B) unsigned char c; foo(&c);
C) unsigned char array[N]; foo(array); /* N != 16 */

and $DEITY knows what else.

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I suppose I could wrap the array in a struct...

struct wrapper {
unsigned char toto[16];
};

and either use that type for parameters, or

typedef struct wrapper toto;

then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.
Exceptions to the above rule still should avoid the use of
ordinary looking type names; make typedef names for array types
stand out in some way that makes it obvious they are unusual, eg,
'xyz_ARRAY'.

Never use type names that are typedefs for array types with
function parameters. (There are some Standard-defined types
which make it hard to follow this rule in some cases, but as
examples such things should be shunned, not imitated.)

I was using a pointer to array type, though. Does your rule
still apply? :)
bar is supposed to call foo.

[what is the way to] pass "p2" directly to foo?

If the typedef and declarations of foo() and bar() are completely
outside of your control, there basically isn't any choice other
than casting. That by itself should be a tip off that something
is wrong.

Yeah, the need to cast sent red flags.
If those things are under your control, change them. The revised
code should (a) follow the advice given above, and (b) not do
any casting. Exactly what interface should be used for foo()
depends on what it is foo() is doing, but it should be possible
to choose a type and a declaration for its single parameter that
satisfies (a) and (b).

Errr... Basically, foo calls functions that expect an array of
16 characters (rather, a pointer to the first element of such
an array, given C's rule for passing arrays as parameters).

Is there no (clean) way to hide the "complexity" of passing
arrays of chars of the right size?

Regards.
 
N

Noob

Barry said:
Noob said:
Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);

The type of p1 is not pointer to unsigned char - char*. Since toto is
an alias for array of 16 char, the type of p1 is pointer to array of
16 unsigned char - unsigned char (*)[16].
int bar(unsigned char *p2);

bar is supposed to call foo.

Then it is bar's job to give foo an argument of the type it expects.
One (round-about) way would be to make a copy of the
contents of p2:

int bar(unsigned char *p2)
{
toto param;
memcpy(param, p2, sizeof param);
return foo(&param);
}

but what is the way to avoid the copy?
(i.e. pass "p2" directly to foo)

If p2 does in fact point to an array of at least 16 unsigned char,
then you could call foo with a simple cast, converting the value in p2
from unsigned char* to unsigned char(*)[16].

On the other hand, it is somewhat unusual for a function to expect a
pointer to array (as opposed to a pointer to first element of the
array). You might want to rethink the signature of foo. You don't
show the code but if foo wants to look at any of the characters
pointed to by p1, it has to use syntax similar to p1[0]. Unless
there is more than one toto in the area p1 points to, this introduces
a level of indirection that is just confusing.


Please see my answer to Tim. I can deal with the confusion,
but I was trying to create an opaque type to guard against
mis-uses of the API.

Regards.
 
T

Tim Rentsch

Noob said:
Tim said:
Noob said:
Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)
As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").
I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?
I was using a pointer to array type, though. Does your rule
still apply? :)

Rhetorical question: is the type specifier in question a typedef
for an array type? In other words I imperiously meant for this
case also to be on the disapproval list. :/
bar is supposed to call foo.

[what is the way to] pass "p2" directly to foo?

If the typedef and declarations of foo() and bar() are completely
outside of your control, there basically isn't any choice other
than casting. That by itself should be a tip off that something
is wrong.

Yeah, the need to cast sent red flags.
If those things are under your control, change them. The revised
code should (a) follow the advice given above, and (b) not do any
casting. Exactly what interface should be used for foo() depends
on what it is foo() is doing, but it should be possible to choose
a type and a declaration for its single parameter that satisfies
(a) and (b).

Errr... Basically, foo calls functions that expect an array of
16 characters (rather, a pointer to the first element of such an
array, given C's rule for passing arrays as parameters).

Is there no (clean) way to hide the "complexity" of passing
arrays of chars of the right size?

I have some ideas about how you might do this, but first I would
like to hear more about the bar() functions and how they fit into
the overall picture.
 
N

Noob

Tim said:
Noob said:
Tim said:
Noob wrote:

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)
As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").
I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?

I'll try and provide some background.

Originally, the entry point to my library was foo, and foo dealt
with 128-bit AES keys, so I had:

typedef uint8_t AESkey[16];
int foo(int op, void *buf, int buflen, AESkey *key);

Later, I had to integrate a third-party library (TPL) that needs
to call foo (nit: it doesn't call foo directly, I have a wrapper
that does some pre- and post- processing). TPL uses "traditional"
pointers as parameters for keys.

So basically, I have defined this wrapper:
int wrap(uint8_t *TPL_key);

and the wrapper is supposed to call foo to get the job done.
Rhetorical question: is the type specifier in question a typedef
for an array type? In other words I imperiously meant for this
case also to be on the disapproval list. :/

I don't know why, but I feel like "pointer to array" should be
able to prevent whole classes of programming errors. But maybe
I'm delusional...
I have some ideas about how you might do this, but first I would
like to hear more about the bar() functions and how they fit into
the overall picture.

OK, I'd like to hear them if you are so inclined. But I've already
"fixed" the code and got rid of the "pointer to array" (to my
chagrin, but progress marches on, or something).

Regards.
 
M

Martin Shobe

Tim said:
Noob said:
Tim Rentsch wrote:

Noob wrote:

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)

As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").
I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?

I'll try and provide some background.

Originally, the entry point to my library was foo, and foo dealt
with 128-bit AES keys, so I had:

typedef uint8_t AESkey[16];
int foo(int op, void *buf, int buflen, AESkey *key);

Later, I had to integrate a third-party library (TPL) that needs
to call foo (nit: it doesn't call foo directly, I have a wrapper
that does some pre- and post- processing). TPL uses "traditional"
pointers as parameters for keys.

So basically, I have defined this wrapper:
int wrap(uint8_t *TPL_key);

and the wrapper is supposed to call foo to get the job done.

If foo and wrap are in the same translation unit, you could do the
following.

// header file.
typedef struct AESkey AESkey;

int foo(int op, void * buf, int buflen, AESkey * key);
int wrap(uint8_t * TPL_key);

// implementation file

struct AESkey
{
uint8_t key;
};

static int foo_imp(int op, void * buf, int buflen, uint8_t * key)
{
// Do stuff here.
}

int foo(int op, void * buf, int buflen, AESkey * key)
{
return foo_imp(op, buf, buflen, key->key);
}

int wrap(uint8_t * key)
{
// Do stuff here.
// Make the call to foo_imp passing the key in directly.
// Do other stuff here.
}

[snip]

Martin Shobe
 
K

Keith Thompson

Noob said:
Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

bar is supposed to call foo.

One (round-about) way would be to make a copy of the
contents of p2:

int bar(unsigned char *p2)
{
toto param;
memcpy(param, p2, sizeof param);
return foo(&param);
}

but what is the way to avoid the copy?
(i.e. pass "p2" directly to foo)

Based on later followups, a `toto` is intended to store a 128-bit AES
key.

Is bar() normally called with a pointer to such a key? If so, bar()
should probably be modified so it takes a `toto*` parameter.

If not, copying 16 bytes to a `toto` object shouldn't be too bad. If it
turns out that the copy is a performance bottleneck, you can probably
get away with a pointer cast:

int bar(unsigned char *p2) {
return foo((toto*)p2);
}

On the other hand, as Tim pointed out, using a typedef for an array type
can cause problems.

If "toto" is mostly treated as an opaque type, and "toto" objects are
handled via toto* pointers, then you'll probably be ok.
 
N

Noob

Martin said:
Tim said:
Noob wrote:

Tim Rentsch wrote:

Noob wrote:

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)

As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").

I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?

I'll try and provide some background.

Originally, the entry point to my library was foo, and foo dealt
with 128-bit AES keys, so I had:

typedef uint8_t AESkey[16];
int foo(int op, void *buf, int buflen, AESkey *key);

Later, I had to integrate a third-party library (TPL) that needs
to call foo (nit: it doesn't call foo directly, I have a wrapper
that does some pre- and post- processing). TPL uses "traditional"
pointers as parameters for keys.

So basically, I have defined this wrapper:
int wrap(uint8_t *TPL_key);

and the wrapper is supposed to call foo to get the job done.

If foo and wrap are in the same translation unit, you could do the
following.

// header file.
typedef struct AESkey AESkey;

int foo(int op, void * buf, int buflen, AESkey * key);
int wrap(uint8_t * TPL_key);

Hmmm, if AESkey is an incomplete type, then users of
the API cannot create these objects.
// implementation file

struct AESkey
{
uint8_t key;
};

I suppose you meant key[16].
I would need to put the full definition in the header.
static int foo_imp(int op, void * buf, int buflen, uint8_t * key)
{
// Do stuff here.
}

int foo(int op, void * buf, int buflen, AESkey * key)
{
return foo_imp(op, buf, buflen, key->key);
}

int wrap(uint8_t * key)
{
// Do stuff here.
// Make the call to foo_imp passing the key in directly.
// Do other stuff here.
}

Thanks for the suggestion.

Regards.
 
M

Martin Shobe

Martin said:
Tim Rentsch wrote:

Noob wrote:

Tim Rentsch wrote:

Noob wrote:

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)

As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").

I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?

I'll try and provide some background.

Originally, the entry point to my library was foo, and foo dealt
with 128-bit AES keys, so I had:

typedef uint8_t AESkey[16];
int foo(int op, void *buf, int buflen, AESkey *key);

Later, I had to integrate a third-party library (TPL) that needs
to call foo (nit: it doesn't call foo directly, I have a wrapper
that does some pre- and post- processing). TPL uses "traditional"
pointers as parameters for keys.

So basically, I have defined this wrapper:
int wrap(uint8_t *TPL_key);

and the wrapper is supposed to call foo to get the job done.

If foo and wrap are in the same translation unit, you could do the
following.

// header file.
typedef struct AESkey AESkey;

int foo(int op, void * buf, int buflen, AESkey * key);
int wrap(uint8_t * TPL_key);

Hmmm, if AESkey is an incomplete type, then users of
the API cannot create these objects.

Considering what you've said of them, I would consider that a good
thing. Provide functions that create (and destroy) them for your users.
// implementation file

struct AESkey
{
uint8_t key;
};

I suppose you meant key[16].
I would need to put the full definition in the header.

Yes, I meant key[16].

[snip]

Martin Shobe
 
T

Tim Rentsch

Noob said:
Tim said:
Noob said:
Tim Rentsch wrote:
Noob wrote:

Consider the following code defining an array type:

typedef unsigned char toto[16];
int foo(toto *p1);
int bar(unsigned char *p2);

Some unsolicted advice:

Au contraire, that's what I was looking for! :)

As a general rule don't use typedef names for array types. The
reason is arrays in C are just different from all other object
types, and using a typedef name for an array is likely to be
confusing.

I'll explain why I did it. To be blunt, A few people on my team
are not very good at C. If my API functions just had "pointer to
unsigned char" parameters, I'd have all sorts of whacky misuses
of the API. [snip examples]

So I wanted to declare an opaque type that could be allocated
with auto storage duration. An array typedef /seemed/ like a
good idea at the time...

I see.. the problem you're trying to solve is basically not a
technical problem but a cultural problem (in the sense of
"engineering culture").
I suppose I could wrap the array in a struct [which is then
typedef'ed to 'toto'] and then I'd have

int foo(toto *p1);
int bar(unsigned char *p2)

but once again, I'd have to cast or copy when bar calls foo.

I'm unclear on how functions like 'bar()' fit into the picture.
Can you explain how they are used and what role they play? Are
they really necessary in the overall design or might they be
provided in some other form?

I'll try and provide some background.

Originally, the entry point to my library was foo, and foo dealt
with 128-bit AES keys, so I had:

typedef uint8_t AESkey[16];
int foo(int op, void *buf, int buflen, AESkey *key);

Later, I had to integrate a third-party library (TPL) that needs
to call foo (nit: it doesn't call foo directly, I have a wrapper
that does some pre- and post- processing). TPL uses "traditional"
pointers as parameters for keys.

Martin Shobe made a good suggestion for how to accomplish the
wrapping without casting. It may not apply, however, if there
are other requirements on the internal data (notably, alignment).
If the foo() function(s) being called are non-trivial, it's
probably worth copying the bytes and doing a type-safe call to
the internal function - might save you some headaches later on.
So basically, I have defined this wrapper:
int wrap(uint8_t *TPL_key);

and the wrapper is supposed to call foo to get the job done.


I don't know why, but I feel like "pointer to array" should be
able to prevent whole classes of programming errors. But maybe
I'm delusional...

Indeed it might, but the problem is not which errors might be
prevented but which potential errors remain. Seeing a
declaration like 'toto *blah' it is very natural to think we can
use the type name 'toto' for an instance of what 'blah' will
point to. However, if 'toto' is an array type, it works
differently for local variables and parameters. A declaration
like 'XYZ *something' carries an unconsciously expected promise
that XYZ is a non-special type (and specifically not an array
type). Maybe something bad will never happen, but if it does
you can be sure you'll be kicking yourself in spades later -
just common sense to avoid cases like that unless there is
a really compelling reason to make an exception.
OK, I'd like to hear them if you are so inclined. But I've already
"fixed" the code and got rid of the "pointer to array" (to my
chagrin, but progress marches on, or something).

After reading your explanation of the wrapping functions I don't
have much to add. There may be some things to try but they
depend on various factors (eg, is it C90 or C99?), including most
prominently what cultural assumptions are present. I do have
one minor suggestion about the declarations of the bar()/wrap()
functions, namely, use an appropriate array type for the "key"
parameter, as for example

int wrap( uint8_t TPL_key[16] );

rather than having the parameter be declared as a pointer. If
the other developers grok the point of such a declaration then
perhaps the "key" parameters for the foo() functions can be
declared the same way. Again though it depends on what the
local culture will understand and/or tolerate.
 
C

Charlton Wilbur

N> I'll explain why I did it. To be blunt, A few people on my team
N> are not very good at C.

....for which the correct response is to improve their C skills, not to
create beautiful new impediments to understanding.

Whether you do this by punishing them for mistakes or rewarding them for
improvement probably depends more on your team than on anything else,
but the path you have chosen will not fix the problem and will not even
mitigate it past the immediate short term.

N> Is there no (clean) way to hide the "complexity" of passing
N> arrays of chars of the right size?

No, because anyone who can't handle that minimal level of complexity has
no business calling himself a programmer.

Charlton
 
E

Eric Sosman

N> I'll explain why I did it. To be blunt, A few people on my team
N> are not very good at C.

...for which the correct response is to improve their C skills, not to
create beautiful new impediments to understanding.

Whether you do this by punishing them for mistakes or rewarding them for
improvement probably depends more on your team than on anything else,
but the path you have chosen will not fix the problem and will not even
mitigate it past the immediate short term.

N> Is there no (clean) way to hide the "complexity" of passing
N> arrays of chars of the right size?

No, because anyone who can't handle that minimal level of complexity has
no business calling himself a programmer.

The "minimal level of complexity" you mention is at the root
of all those buffer overflow vulnerabilities. If everyone who
ever ran off the end of a buffer were drummed out of the programming
profession, who'd be left to write code?

Let's face it: People make mistakes. Some make more than others,
some fewer, but nobody makes none (no, that's not a double negative).
An interface design that makes mistakes more difficult is an impediment
to error -- and there's nothing wrong with obstructing error.
 
C

Charlton Wilbur

ES> Let's face it: People make mistakes. Some make more than
ES> others, some fewer, but nobody makes none (no, that's not a
ES> double negative). An interface design that makes mistakes more
ES> difficult is an impediment to error -- and there's nothing wrong
ES> with obstructing error.

Indeed; however, I see no reason to believe that the design in question
actually does obstruct error, and is far more likely to obscure it.

Charlton
 
L

Les Cargill

Eric said:
The "minimal level of complexity" you mention is at the root
of all those buffer overflow vulnerabilities.

No. For a given set of tools, it is *eminently* possible to write
code - yes, even using primitive, K&R 'C' library functions - that
enforce constraints such that buffer overflows are impossible.

I know this because we all did this in the Dark Ages of the 20th Century.
If everyone who
ever ran off the end of a buffer were drummed out of the programming
profession, who'd be left to write code?

Can we give them a time-out, then? We literally used to have
tokens of "esteem" - like a memory chip - that we would award
to people for this sort of thing. Granted, the culture then was
much more collegial than perhaps what happens today ( had
anyone objected, we would have stopped, but it was like how
safety works in industry - we were watching out for each other )
and by golly, we didn't have many (or possibly any) of those.

Let's face it: People make mistakes.

People also make meta-mistakes in the service of preventing simple,
honest mistakes.
Some make more than others,
some fewer, but nobody makes none (no, that's not a double negative).
An interface design that makes mistakes more difficult is an impediment
to error -- and there's nothing wrong with obstructing error.

Error is *always an element in a trade space*... so I'd bite that
"always" back a bit if I were you....

the *largest single population* or memory overwrites I ever witnessed
was on one of those bloated '90s C++ projects where the interface
class design presumably precluded all those memory overwrites.

Hubris is also a human ... thing.
 

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,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top