Common Problems that Compilers Don't Catch

B

bwaichu

I am starting this thread after having run into two separate
programming problems,
where the compiler offered no help. The compiler did not even warn.
The programs
compiled fine. And the programs even appeared to work.

The first case was passing directly a variable of type char **.

Here's an example:

prototype: void func(char **);

WRONG

char **var;

func(var);

CORRECT

char *var;

func(&var);

The problem with the above is that the pointer is never initialized.

The second problem I ran into was typecasting an integer to a pointer.

For example:

int var;

foo((void *)var);

The above causes a problem since a pointer and an integer are two
really different types of variables. The problem is that function
required a pointer to be passed, but I needed to work with an integer
in the function I was calling.

Here's the correct way to pass the variable:

foo(&var);

to access the integer

foo(*(int *)var);

Please add additional problems, where the compiler will just compile
without warning or add some clarification to the above examples and
explanations. I prefer to write good code versus code that just works.
 
I

Ian Collins

I am starting this thread after having run into two separate
programming problems,
where the compiler offered no help. The compiler did not even warn.
The programs
compiled fine. And the programs even appeared to work.

The first case was passing directly a variable of type char **.

Here's an example:

prototype: void func(char **);

WRONG

char **var;

func(var);
Lint would pick this up - use it!
The second problem I ran into was typecasting an integer to a pointer.

For example:

int var;

foo((void *)var);
You used a cast, which tells the compiler you know what you are doing
and suppresses any warnings. <OT> This one reason why C++ added specific
casts </OT>
 
F

Frederick Gotham

(e-mail address removed) posted:
I am starting this thread after having run into two separate programming
problems, where the compiler offered no help. The compiler did not even
warn. The programs compiled fine. And the programs even appeared to
work.


Computers are our slaves. Your code told the computer what to do, so it did
it.

The first case was passing directly a variable of type char **.

Here's an example:

prototype: void func(char **);

WRONG

char **var;

func(var);


I presume you would like a warning such as:

usage of uninitialised variable


Become more familiar with pointer variables and you won't be making such
mistakes.

The second problem I ran into was typecasting an integer to a pointer.

For example:

int var;

foo((void *)var);

The above causes a problem since a pointer and an integer are two
really different types of variables.


So why perform the cast?

The problem is that function required a pointer to be passed, but I
needed to work with an integer in the function I was calling.


What, something like this:

void Func(void *p)
{
int i = (int)p;

DoSomething(i);
}

int main()
{
int i = 5;

Func( (void*)i );
}

That's a horrid design (and isn't guaranteed to work). If anything, you
should use the "void*" to store the ADDRESS of the integer, rather than the
integer itself:

void Func(void *p)
{
int i = *(int*)p;

DoSomething(i);
}

int main()
{
int i = 5;

Func(&i);
}

Please add additional problems, where the compiler will just compile
without warning or add some clarification to the above examples and
explanations. I prefer to write good code versus code that just works.


All I can say is that you need to practise C programming more.
 
H

Herbert Rosenau

(e-mail address removed) posted:



Computers are our slaves. Your code told the computer what to do, so it did
it.




I presume you would like a warning such as:

usage of uninitialised variable


Become more familiar with pointer variables and you won't be making such
mistakes.




So why perform the cast?




What, something like this:

void Func(void *p)
{
int i = (int)p;

enters UB. a pinter is not an int. So casing it to int will produce
something but seldom what you thinks it should produce.
DoSomething(i);
}

int main()
{
int i = 5;

Func( (void*)i );
}

That's a horrid design (and isn't guaranteed to work).

It is goiaranteed NOT to work.

If anything, you
should use the "void*" to store the ADDRESS of the integer, rather than the
integer itself:

void Func(void *p)
{
int i = *(int*)p;
DoSomething(i);
}

int main()
{
int i = 5;

Func(&i);
}




All I can say is that you need to practise C programming more.


--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2 Deutsch ist da!
 
F

Frederick Gotham

Herbert Rosenau posted:
enters UB. a pinter is not an int. So casing it to int will produce
something but seldom what you thinks it should produce.


Not UB, but rather implementation-specific behaviour. It's possible that
however the following expression could result in a trap representation:

(int)p

It is goiaranteed NOT to work.


No, it's NOT guaranteed not to work. The following works fine on my system:

#include <stdio.h>

void Func(void const *const p)
{
printf("%u", (unsigned)p);
}

int main(void)
{
unsigned i = 123;

Func((void const*)i);

return 0;
}

It's not guaranteed to work by the Standard, and thus is non-portable --
but nonetheless, there's no guarantee that it WON'T work.
 
K

Keith Thompson

Frederick Gotham said:
(e-mail address removed) posted: [...]
Here's an example:

prototype: void func(char **);

WRONG

char **var;

func(var);


I presume you would like a warning such as:

usage of uninitialised variable

The standard doesn't require such a warning, but any decent compiler
should give you one if you invoke it with the right arguments. (In
some cases, just enabling warnings won't be enough; you may also have
to enable optimization to force the compiler to do the analysis
necessary to catch the error.)

Of course it's better not to make such an error in the first place.
 
K

Keith Thompson

Herbert Rosenau said:
enters UB. a pinter is not an int. So casing it to int will produce
something but seldom what you thinks it should produce.

Casting a pointer to int does not *necessarily* invoke undefined
behavior. C99 6.3.2.3p6:

Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.

(The phrase "Except as previously specified" refers to null pointer
constants.) If your implementation provides intprt_t and/or
uintptr_t, you can convert a void* to either of those types without
risk of undefined behavior.

That's not to say that converting pointers to integers is a good idea.
If you're writing low-level code *and* you know exactly what you're
doing, it can be useful. If not, you should avoid it. Pointers are
pointers, and integers are integers.
It is goiaranteed NOT to work.

No, it's not guaranteed not to work. If the implementation allows int
and void* to be converted back and forth, it could do exactly what you
want it to do. But yes, it's most likely a horrid design, unless
there's some really good reason to do it that way.
 
E

ena8t8si

Keith said:
Casting a pointer to int does not *necessarily* invoke undefined
behavior. C99 6.3.2.3p6:

Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.

(The phrase "Except as previously specified" refers to null pointer
constants.)

Also converting a pointer to _Bool; always defined.
 
A

Andrew Poelstra

I am starting this thread after having run into two separate
programming problems,
where the compiler offered no help. The compiler did not even warn.
The programs
compiled fine. And the programs even appeared to work.

The first case was passing directly a variable of type char **.

WRONG
char **var;
func(var);

CORRECT
char *var;
func(&var);

The problem with the above is that the pointer is never initialized.

My compiler warns about that, informing me that "var may be used
uninitialized".
The second problem I ran into was typecasting an integer to a pointer.

For example:

int var;

foo((void *)var);

The above causes a problem since a pointer and an integer are two
really different types of variables. The problem is that function
required a pointer to be passed, but I needed to work with an integer
in the function I was calling.

The point of casting is to shut the compiler up. (Actually, there are
other, much more correct, uses, but you've used it here as a silencer.)

When investigating a murder, you can't complain about faulty guns that
don't make loud bangs when silenced.
 

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,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top