By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,236 Members | 1,795 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,236 IT Pros & Developers. It's quick & easy.

Program crashes when running it outside dev environment

P: n/a
z
I use Visual C 2005 to develop my programs. One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option. If I try to launch the debug on the
crashing program, it'll close before the debugger opens. Any
suggestions as to how I should proceed? Thanks in advance.

Jun 8 '07 #1
Share this Question
Share on Google+
41 Replies


P: n/a
z wrote:
| I use Visual C 2005 to develop my programs. One in particular is
| crashing in very specific and hard to replicate situations, made
| worse by the fact it only crashes when run -outside- the dev - as
| an exe, not from the Debug option. If I try to launch the debug on
| the crashing program, it'll close before the debugger opens. Any
| suggestions as to how I should proceed? Thanks in advance.

It sounds as if you should first focus on the code that handles those
"very specific situations".

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto/
Jun 8 '07 #2

P: n/a
z
It sounds as if you should first focus on the code that handles those
"very specific situations".
Oops, maybe 'specific' was a bad word. I meant 'ocurring in a
different point of code depending on how the program is compiled'.
Usually in the middle of a fopen/fread operation, but when it isn't it
just likes to crash anywhere it feels like.

Jun 8 '07 #3

P: n/a
z wrote:
I use Visual C 2005 to develop my programs. One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option. If I try to launch the debug on the
crashing program, it'll close before the debugger opens. Any
suggestions as to how I should proceed? Thanks in advance.
1) You should learn how to debug. The first rule is:
READ THE DOCUMENTATION.
Your compiler can spring into action with its debugger
when a crash occurs. Set it up to do that, and then you
will find the reason of the crash.
2) When you find the source code of the crash you will probably
notice that you are experiencing the consequences of the bug,
not a direct cause of the bug itself. Beware of quick
conclusions.

Jun 8 '07 #4

P: n/a
On Fri, 08 Jun 2007 05:57:28 -0000, z <za********@gmail.comwrote:
>I use Visual C 2005 to develop my programs. One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option. If I try to launch the debug on the
crashing program, it'll close before the debugger opens. Any
suggestions as to how I should proceed? Thanks in advance.
Your best bet is to post a complete, as-small-as-possible, program in
the form of source code that reproduces your problem. Keep in mind
that this is c.l.c, so anything specific to Visual C 2005 or Windows
and that is not standard C is, officially, off-topic for this
newsgroup.

If your problem is related to using standard C, then this is the right
newsgroup to seek help. If not, then there are more appropriate
newsgroups out there that will be better able to serve you. Either
way, I'm sure that if you post some source code, the readers in this
newsgroup will be able to guide you one way or the other.

Best regards
--
jay
Jun 8 '07 #5

P: n/a
"z" <za********@gmail.comschrieb im Newsbeitrag
news:11**********************@w5g2000hsg.googlegro ups.com...
>
>It sounds as if you should first focus on the code that handles those
"very specific situations".

Oops, maybe 'specific' was a bad word. I meant 'ocurring in a
different point of code depending on how the program is compiled'.
Usually in the middle of a fopen/fread operation, but when it isn't it
just likes to crash anywhere it feels like.
Show some cut down to the minimum but still compilable code that inhibits
that behavoir.

Guess is that you're stubling accross some undefined behavoir.

Bye, Jojo
Jun 8 '07 #6

P: n/a
z wrote:
I use Visual C 2005 to develop my programs. One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option. If I try to launch the debug on the
crashing program, it'll close before the debugger opens. Any
suggestions as to how I should proceed? Thanks in advance.
Does windows give you a core file you can debug?

--
Ian Collins.
Jun 8 '07 #7

P: n/a
z said:
I use Visual C 2005 to develop my programs.
Oh, my poor dear chap, I do sympathise.
One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option.
Sounds like a Heisenbug to me - a wild pointer, an array bounds
violation, mucking about with memory you don't own, something like
that. They can be really, *really* frustrating to chase down. I know
this because I used to find it so, and the debugger isn't as much help
as it might be in these situations, for the reason you outline.

A few years ago I discovered that, as I started tightening up my
attitude to the language lawyer stuff we discuss so much here in clc, I
was getting fewer and fewer Heisenbugs, and they were becoming easier
and easier to fix.

So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast
4) think.

Step 4 is hardest, of course, especially with nothing to go on. You,
however, can see your program, which we can't. I suggest you check all
your pointer and array stuff *very* carefully indeed.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #8

P: n/a
Richard Heathfield wrote:
z said:

>One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option.
[...]

So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast
4) think.
Good advice, I can add

5) use a memory tool, on Win32 I use BoundsChecker, but there are also
free tools out there.

6) Add run-time checks

A) define e.g. a macro PRE to detect pre-condition failures in functions
B) define e.g. a macro POST to detect post-conditions failures in functions
C) define e.g. a macro IMPOSSIBLE_STATE to detect exactly that.

7) write test programs: stress-test, random-input test etc

8) use a lint tool

9) Think about race-conditions
--
Tor <torust [at] online [dot] no>
Jun 8 '07 #9

P: n/a
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast
I'm with you right up to the last clause. Are you saying you never
actually *need* a cast? Because if you ever really do need one and
forget to put it in and the compiler gives a diagnostic, you're advice
is to... do what? Don't fix it? I'm sure you don't mean that, since
then you'd never compile without any diagnostics! ;-)
4) think.
Dave

--
D.a.v.i.d T.i.k.t.i.n
t.i.k.t.i.n [at] a.d.v.a.n.c.e.d.r.e.l.a.y [dot] c.o.m
Jun 8 '07 #10

P: n/a
David Tiktin said:
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you never
actually *need* a cast?
No, there are (rare) occasions when you do need a cast. But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error. So adding a cast is not the
right way to fix a diagnostic message. If the choice is between adding
bad code and putting up with a bad warning, I'll live with the bad
warning.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #11

P: n/a
Richard Heathfield wrote:
David Tiktin said:
>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you never
actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error. So adding a cast is not the
right way to fix a diagnostic message. If the choice is between adding
bad code and putting up with a bad warning, I'll live with the bad
warning.
I can't think of a concrete example of a cast which causes a constraint
violation or syntax error when left out either, but diagnostics are
permitted for other code as well.

#include <stdio.h>
int main(void) {
int *p = NULL;
printf("%p\n", p);
}

example.c:4: warning: format ‘%p’ expects type ‘void *’, but argument 2 has
type ‘int *’

And a cast is the right way to fix the bug.
Jun 8 '07 #12

P: n/a
In article <f4**********@news3.zwoll1.ov.home.nl>,
Harald van Dijk <tr*****@gmail.comwrote:
>example.c:4: warning: format ‘%p’ expects type ‘void *’, but
Who was the moron who though it would be a good idea to use non-ascii
characters in error messages just to get prettier quotes if you happen
to have a UTF-8 display?

(Probably the same one who thought it was a good idea for manual pages.)

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jun 8 '07 #13

P: n/a
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
David Tiktin said:
>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you
never actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I
don't know of any occasion where you *need* a cast AND omitting it
violates a constraint or constitutes a syntax error. So adding a
cast is not the right way to fix a diagnostic message. If the
choice is between adding bad code and putting up with a bad
warning, I'll live with the bad warning.
But now you're changing your advice. You get diagnostics for things
other than constraint violations and syntax errors. On the highest
warning levels, you may well get a diagnostic on code like this:

char * ptr = buffer;
int c;

while ((c = getchar()) != EOF)
{
*ptr++ = c;
}

diag.c(73) : warning C4244: '=' : conversion from 'int ' to 'char ',
possible loss of data

That's with MSVC 6.0 and -W4.

Do you think loss of precision diagnostics are "bad warnings"? (I
don't.) Shouldn't we fix this with a cast?

*ptr++ = (char) c;

If not, what do you suggest? If we do nothing, we'll have to think
about that warning every time we build, because an *actual* loss of
precision is often a serious bug.

Dave

--
D.a.v.i.d T.i.k.t.i.n
t.i.k.t.i.n [at] a.d.v.a.n.c.e.d.r.e.l.a.y [dot] c.o.m
Jun 8 '07 #14

P: n/a
In article <Vu******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>No, there are (rare) occasions when you do need a cast. But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
I must be misunderstanding you...

struct foo {int id; ...};

/* comparison function for qsort() */
int compar(void *a, void *b)
{
return ((struct foo *)a)->id - ((struct foo *)b)->id;
}

Omitting the casts here would be a constraint violation.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jun 8 '07 #15

P: n/a
Harald van =?UTF-8?B?RMSzaw==?= wrote:
>
Richard Heathfield wrote:
But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
I can't think of a concrete example of a cast which
causes a constraint
violation or syntax error when left out either, but diagnostics are
permitted for other code as well.
You need a cast if you're writing a function like strchr, strstr
or bsearch, which returns a pointer to an unqualified type,
which is derived from a parameter that points to a qualified type.

char *strstr(const char *s1, const char *s2)
{
const int c = *s2++;

if (c != '\0') {
const size_t n = strlen(s2);

s1 = strchr(s1, c);
while (s1 != NULL && strncmp(s1 + 1, s2, n) != 0) {
s1 = strchr(s1 + 1, c);
}
}
return (char *)s1;
}
--
pete
Jun 8 '07 #16

P: n/a
David Tiktin <dt*****@nospam.totally-bogus.comwrites:
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>David Tiktin said:
>>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you
never actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I
don't know of any occasion where you *need* a cast AND omitting it
violates a constraint or constitutes a syntax error. So adding a
cast is not the right way to fix a diagnostic message. If the
choice is between adding bad code and putting up with a bad
warning, I'll live with the bad warning.

But now you're changing your advice. You get diagnostics for things
other than constraint violations and syntax errors. On the highest
warning levels, you may well get a diagnostic on code like this:

char * ptr = buffer;
int c;

while ((c = getchar()) != EOF)
{
*ptr++ = c;
}

diag.c(73) : warning C4244: '=' : conversion from 'int ' to 'char ',
possible loss of data

That's with MSVC 6.0 and -W4.

Do you think loss of precision diagnostics are "bad warnings"? (I
don't.) Shouldn't we fix this with a cast?

*ptr++ = (char) c;

If not, what do you suggest? If we do nothing, we'll have to think
about that warning every time we build, because an *actual* loss of
precision is often a serious bug.
c is of type int. We know that it's a value returned by getchar(),
and that it's not equal to EOF, so it must be within the range of
unsigned char, 0..UCHAR_MAX.

Suppose UCHAR_MAX==255 and char is signed, with CHAR_MAX==127, and
suppose c==200. Then the conversion of the value 200 to type char
either yields an implementation-defined value or raises an
implementation-defined signal (C99 6.3.1.3p3).

(In most implementations the conversion will yield a "sensible"
result, most likely -55.)

I suspect that's not what MSVC is complaining about; my guess is that
it would produce the same warning if ptr were declared as unsigned
char*. (And of course the code invokes UB if you overflow the buffer;
it's like gets(), but reading an entire file rather than a single
line.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 8 '07 #17

P: n/a
Harald van D?k said:
Richard Heathfield wrote:
>David Tiktin said:
>>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:

So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you never
actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I don't
know of any occasion where you *need* a cast AND omitting it violates
a constraint or constitutes a syntax error. So adding a cast is not
the right way to fix a diagnostic message. If the choice is between
adding bad code and putting up with a bad warning, I'll live with the
bad warning.

I can't think of a concrete example of a cast which causes a
constraint violation or syntax error when left out either, but
diagnostics are permitted for other code as well.
Yes indeed, but casts are not the right way to fix these diagnostic
messages. (Peace! I know what you're saying.) After all, any compiler
can issue any diagnostic message for any reason it likes. For example:

int main(void)
{
int i = 42;
return 0;
}

Warning: today is Saturday. (Suppress this warning by casting 42 to
double.)

Would you obey that suggestion? I certainly wouldn't. (In fact, I'd be
tempted to Get A Better Compiler, but of course that isn't always an
option.)

Nevertheless, your example still needs to be addressed, so let's read
on.
#include <stdio.h>
int main(void) {
int *p = NULL;
printf("%p\n", p);
}

example.c:4: warning: format ?%p? expects type ?void *?, but argument
2 has type ?int *?

And a cast is the right way to fix the bug.
Yes, a cast is the right way to fix the *bug*. The code is broken
because a needed cast is absent. But you'd have to fix that *anyway*.
The fact that the compiler was kind enough to produce a diagnostic
message is neither here nor there.

This may seem like a fine line I'm treading (and perhaps it *is* a fine
line), but I think there's an important distinction between "fixing the
code" and "changing the code in such a way that you don't get any
warnings", especially when implementations have such licence to produce
any messages they like. In your example, the cast will actually perform
both functions - it will fix the code /and/ suppress the warning. The
former is important. The latter, however, is not particularly
important.

I used to be one of those who insist on a clean compile. Nowadays,
however, I prefer to be one of those who insist on correct code. If I
get a clean compile *as well*, that's a bonus. Therefore, when I get
diagnostic messages, I investigate them. If they have any merit, I fix
the code. If not, I will probably annotate the code with a comment that
explains what warning I'm getting for it, and why, and why I'm not
going to change the code. I make an exception for obvious stuff, such
as gcc's constant diatribes against code such as struct foo bar = {0};
which doesn't really merit a comment, as it's so obviously right.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #18

P: n/a
David Tiktin said:
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>David Tiktin said:
>>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:

So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you
never actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I
don't know of any occasion where you *need* a cast AND omitting it
violates a constraint or constitutes a syntax error. So adding a
cast is not the right way to fix a diagnostic message. If the
choice is between adding bad code and putting up with a bad
warning, I'll live with the bad warning.

But now you're changing your advice.
Yes, I am, aren't I? I don't recall signing a contract... :-)

I think my best defence (which is intended sincerely but might sound a
bit self-serving and pompous, for which I apologise in advance) can be
found in "The Tao of Programming", by Geoffrey James:

"There once was a master programmer who wrote unstructured programs. A
novice programmer, seeking to imitate him, also began to write
unstructured programs. When the novice asked the master to evaluate his
progress, the master criticized him for writing unstructured programs,
saying, ``What is appropriate for the master is not appropriate for the
novice. You must understand the Tao before transcending structure.''"

Actually, I try not to write unstructured programs! But my point is
this: a relative newcomer to C is generally less skilled at
interpreting diagnostic messages than someone who has been in the game
for a few years. The temptation newcomers often have is to keep fixing
stuff *until it compiles*, at which point they tend to dismiss any
remaining warnings as "only warnings", whereas they (and their
programs) would benefit greatly from treating *every* diagnostic
message as being important. Over time, they will learn which messages
truly can be overlooked and which cannot. In the meantime, adopting a
policy of "cast away the diagnostic" is likely to lead to bad code and
sloppy habits.
You get diagnostics for things
other than constraint violations and syntax errors. On the highest
warning levels, you may well get a diagnostic on code like this:

char * ptr = buffer;
int c;

while ((c = getchar()) != EOF)
{
*ptr++ = c;
}

diag.c(73) : warning C4244: '=' : conversion from 'int ' to 'char ',
possible loss of data

That's with MSVC 6.0 and -W4.
Sure. Would you add a cast there? I wouldn't.
Do you think loss of precision diagnostics are "bad warnings"? (I
don't.)
No, but they can be a nuisance at times! (And this, indeed, is one such
time.)
Shouldn't we fix this with a cast?
No. How does it fix the code? Does it remove the loss of precision? Of
course not!
*ptr++ = (char) c;

If not, what do you suggest? If we do nothing, we'll have to think
about that warning every time we build,
Add a comment to the code, explaining why no loss of precision is
involved.
because an *actual* loss of precision is often a serious bug.
So why hide it with a cast?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #19

P: n/a
Richard Tobin said:
In article <Vu******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>>No, there are (rare) occasions when you do need a cast. But I don't
know of any occasion where you *need* a cast AND omitting it violates
a constraint or constitutes a syntax error.

I must be misunderstanding you...

struct foo {int id; ...};

/* comparison function for qsort() */
int compar(void *a, void *b)
{
return ((struct foo *)a)->id - ((struct foo *)b)->id;
}

Omitting the casts here would be a constraint violation.
In some respects, that's a well-constructed example. (In other respects,
not so good.) I'm afraid my only answer is that I wouldn't write it
like that, because it's broken in at least two ways. I'd write it like
this:

int compar(const void *vp1, const void *vp2)
{
const struct foo *p1 = vp1;
const struct foo *p2 = vp2;
return (p1->id p2->id) - (p1->id < p2->id);
}

My version, unlike yours, is compatible with qsort. My version, unlike
yours, doesn't risk overflow. And my version, unlike yours, doesn't use
casts, and yet there is no constraint violation or syntax error.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #20

P: n/a
pete said:
Harald van =?UTF-8?B?RMSzaw==?= wrote:
>>
Richard Heathfield wrote:
>
But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
>I can't think of a concrete example of a cast which
causes a constraint
violation or syntax error when left out either, but diagnostics are
permitted for other code as well.

You need a cast if you're writing a function like strchr, strstr
or bsearch, which returns a pointer to an unqualified type,
which is derived from a parameter that points to a qualified type.
There's a good reason why those are library functions. :-)

In general, casting away const is not something of which I can bring
myself to approve.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 8 '07 #21

P: n/a
In article <B7******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>I'd write it like this:

int compar(const void *vp1, const void *vp2)
{
const struct foo *p1 = vp1;
const struct foo *p2 = vp2;
return (p1->id p2->id) - (p1->id < p2->id);
}

My version, unlike yours, is compatible with qsort.
Normally I'm not one to criticise pedantry, but really that is
irrelevant to the point at hand.
>My version, unlike yours, doesn't risk overflow.
And again. Anyway, you have no reason to suppose that "id" can take
values that could cause overflow.
>And my version, unlike yours, doesn't use
casts, and yet there is no constraint violation or syntax error.
If you're willing to change the program to use assignments instead of
casts, obviously casts aren't necessary. Hardly any C constructs are
necessary by that standard, and your assertion was vacuous.

Another example where a cast is needed is when converting one kind of
struct pointer to another (which is allowed under some circumstances).
But of course you can say that you wouldn't write the program like
that, or you would use a temporary void * variable. But it is again
an example of an expression that would be a constraint violation
without the the cast. And of course converting between pointers
and uintptr_t in C99.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jun 9 '07 #22

P: n/a
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
David Tiktin said:
>You get diagnostics for things
other than constraint violations and syntax errors. On the
highest warning levels, you may well get a diagnostic on code
like this:

char * ptr = buffer;
int c;

while ((c = getchar()) != EOF)
{
*ptr++ = c;
}

diag.c(73) : warning C4244: '=' : conversion from 'int ' to 'char
', possible loss of data

That's with MSVC 6.0 and -W4.

Sure. Would you add a cast there? I wouldn't.
Yes, I would and do.
>Do you think loss of precision diagnostics are "bad warnings"?
(I don't.)

No, but they can be a nuisance at times! (And this, indeed, is one
such time.)
>Shouldn't we fix this with a cast?

No. How does it fix the code? Does it remove the loss of
precision? Of course not!
Agreed it does not reomove the loss of precision. But the cast just
tells the compiler, "I know there's a loss of precision, and it's OK.
I accept that." The compiler respects our judgement when we clearly
state it. That's one of the reasons I program in C!
> *ptr++ = (char) c;

If not, what do you suggest? If we do nothing, we'll have to
think about that warning every time we build,

Add a comment to the code, explaining why no loss of precision is
involved.
The cast is, IMHO, better. My memory isn't what it used to be, and I
likely won't remember which for each of the hundreds of source files
I maintain which had which diagnostic which was really OK. With the
cast, I don't have to open the source file and find the comment every
damn time I build the thing! ;-)
>because an *actual* loss of precision is often a serious bug.

So why hide it with a cast?
In the case at hand, nothing is being "hidden." I was warned and
determined that the danger I was being warned about did not exist. I
record that fact with a cast.

Really, your first instinct in the advice you gave was right: get rid
of all the warnings. I find it a little hard to believe either that
your code contains no casts or that your builds are full of warnings
you just ignore. (BTW, that's meant as a compliment ;-)

Dave

--
D.a.v.i.d T.i.k.t.i.n
t.i.k.t.i.n [at] a.d.v.a.n.c.e.d.r.e.l.a.y [dot] c.o.m
Jun 9 '07 #23

P: n/a
pete <pf*****@mindspring.comwrites:
Harald van =?UTF-8?B?RMSzaw==?= wrote:
>Richard Heathfield wrote:
But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
>I can't think of a concrete example of a cast which
causes a constraint
violation or syntax error when left out either, but diagnostics are
permitted for other code as well.

You need a cast if you're writing a function like strchr, strstr
or bsearch, which returns a pointer to an unqualified type,
which is derived from a parameter that points to a qualified type.

char *strstr(const char *s1, const char *s2)
{
[snip]
return (char *)s1;
}
I'd argue that that's a bug in the specification of strstr(), which
IMHO *should* be declared as:

const char *strstr(const char *s1, const char *s2)

I suppose it's declared the way it is to avoid breaking pre-ANSI code
that assigns the result of strstr to an unqualified char* object.
(The const qualifier could safely be added to the parameters without
breaking anything.) It's the same rationale as the one for not making
string literals const.

With strstr and friends, it's possible to discard the const qualifier
from a const char* with neither a cast nor a diagnostic. I think if
the language were being designed from scratch today, this would have
been done differently.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 9 '07 #24

P: n/a
Richard Tobin wrote:
Richard Heathfield <rj*@see.sig.invalidwrote:
>No, there are (rare) occasions when you do need a cast. But I
don't know of any occasion where you *need* a cast AND omitting
it violates a constraint or constitutes a syntax error.

I must be misunderstanding you...

struct foo {int id; ...};

/* comparison function for qsort() */
int compar(void *a, void *b)
{
return ((struct foo *)a)->id - ((struct foo *)b)->id;
}

Omitting the casts here would be a constraint violation.
int compar(const void *a, const void *b) {
const struct foo *ap = a, *bp = b;

/* now operate with *ap and *bp, no casts */
return (*ap->id *bp->id) - (*bp->id *ap->id);
}

avoiding sneaky overflows and descent into UB. :-)

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 9 '07 #25

P: n/a
David Tiktin wrote:
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you
never actually *need* a cast? Because if you ever really do
need one and forget to put it in and the compiler gives a
diagnostic, you're advice is to... do what? Don't fix it?
I'm sure you don't mean that, since then you'd never compile
without any diagnostics! ;-)
AFAICS the only place you actually NEED a cast is when passing
variables to printf (and similar variadic) functions. Else they
will assume integers are passed.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
<http://kadaitcha.cx/vista/dogsbreakfast/index.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 9 '07 #26

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
David Tiktin said:
>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you never
actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
Neither do I but what do you do in the recently discussed case of
pointers to pointers to types that lack a qualifier? For example, do
you use a cast to pass, say, a char ** to a function declared:

void f(const char *const *ccp);

This seems to me to be a case where the cast in:

char **p;
...
f((const char *const *)p);

is the best solution despite it being there simply to silence a
diagnostic. Of course the cast is not needed -- you could go via an
otherwise redundant void * variable, but it that really what you would
do?

--
Ben.
Jun 9 '07 #27

P: n/a
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
>Harald van =?UTF-8?B?RMSzaw==?= wrote:
>>Richard Heathfield wrote:
But I don't know
of any occasion where you *need* a cast AND omitting it violates a
constraint or constitutes a syntax error.
I can't think of a concrete example of a cast which
causes a constraint
violation or syntax error when left out either, but diagnostics are
permitted for other code as well.
You need a cast if you're writing a function like strchr, strstr
or bsearch, which returns a pointer to an unqualified type,
which is derived from a parameter that points to a qualified type.

char *strstr(const char *s1, const char *s2)
{
[snip]
> return (char *)s1;
}

I'd argue that that's a bug in the specification of strstr(), which
IMHO *should* be declared as:

const char *strstr(const char *s1, const char *s2)

I suppose it's declared the way it is to avoid breaking pre-ANSI code
that assigns the result of strstr to an unqualified char* object.
(The const qualifier could safely be added to the parameters without
breaking anything.) It's the same rationale as the one for not making
string literals const.

With strstr and friends, it's possible to discard the const qualifier
from a const char* with neither a cast nor a diagnostic. I think if
the language were being designed from scratch today, this would have
been done differently.
<OTThe C++ solution was to provide two versions:

const char *strstr(const char *s1, const char *s2);
char *strstr(char *s1, const char *s2);

</OT>

--
Ian Collins.
Jun 9 '07 #28

P: n/a
Richard Tobin said:
In article <B7******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
<snip>
Normally I'm not one to criticise pedantry,
Whew! :-)
but really that is irrelevant to the point at hand.
True, but since when did that stop any self-respecting clc-er?

<snip>
>>And my version, unlike yours, doesn't use
casts, and yet there is no constraint violation or syntax error.

If you're willing to change the program to use assignments instead of
casts, obviously casts aren't necessary.
Right. That's kind of my point. It is generally possible to fix broken
code without using casts.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 9 '07 #29

P: n/a
David Tiktin said:
On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>David Tiktin said:
<snip>
>>Shouldn't we fix this with a cast?

No. How does it fix the code? Does it remove the loss of
precision? Of course not!

Agreed it does not reomove the loss of precision. But the cast just
tells the compiler, "I know there's a loss of precision, and it's OK.
I accept that."
C&V, please.

<snip>
Really, your first instinct in the advice you gave was right: get rid
of all the warnings.
It's the right advice for a relative newcomer to C, I think. But so was
my suggestion about not adding casts, I think.
I find it a little hard to believe either that
your code contains no casts or that your builds are full of warnings
you just ignore. (BTW, that's meant as a compliment ;-)
It's a kind thought, for which I thank you. In fact, there are hardly
any casts in my code, and the ones that are there are generally
necessary ones. Any unnecessary ones tend to be hangovers from old
habits, which have so far survived occasional sporadic bursts of
cleanup.

As for warnings, the vast majority I get (at least in gcc) are from the
code pattern T object = {0}; - and I haven't yet found a *good*
workaround for getting rid of those. If it were topical, I'd invite
suggestions, but it isn't so I won't.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 9 '07 #30

P: n/a
Richard Tobin wrote:
Richard Heathfield <rj*@see.sig.invalidwrote:
>I'd write it like this:

int compar(const void *vp1, const void *vp2)
{
const struct foo *p1 = vp1;
const struct foo *p2 = vp2;
return (p1->id p2->id) - (p1->id < p2->id);
}

My version, unlike yours, is compatible with qsort.

Normally I'm not one to criticise pedantry, but really that is
irrelevant to the point at hand.
My version, unlike yours, doesn't risk overflow.

And again. Anyway, you have no reason to suppose that "id" can
take values that could cause overflow.
IIRC the id field was declared as an int. Subtracting (or adding)
ints can always create overflows.

--
Please do not top-post. Your answer belongs after (or intermixed
with) the quoted material to which you reply, after snipping all
irrelevant material. See the following links:

<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/ (taming google)
<http://members.fortunecity.com/nnqweb/ (newusers)

--
Posted via a free Usenet account from http://www.teranews.com

Jun 9 '07 #31

P: n/a
CBFalconer <cb********@yahoo.comwrites:
David Tiktin wrote:
>On 08 Jun 2007, Richard Heathfield <rj*@see.sig.invalidwrote:
>>So my suggestions would be:

1) crank up your warning level to the max
2) turn off any extensions you can live without
3) fix every single diagnostic message, and *never* with a cast

I'm with you right up to the last clause. Are you saying you
never actually *need* a cast? Because if you ever really do
need one and forget to put it in and the compiler gives a
diagnostic, you're advice is to... do what? Don't fix it?
I'm sure you don't mean that, since then you'd never compile
without any diagnostics! ;-)

AFAICS the only place you actually NEED a cast is when passing
variables to printf (and similar variadic) functions. Else they
will assume integers are passed.
No, the compiler will assume that each argument is of the (possibly
promoted) type of the expression, whatever that happens to be. This
type isn't necesarily int, or even an integer type. For a variadic
function, it just won't attempt to coerce the argument to the actual
parameter type, because it doesn't know it.

It's always *possible* to use printf without casting:

int n; /* want to print the address of n */
void *addr_of_n = &n;
printf("&n = %p\n", addr_of_n);

but it's cleaner just to use a cast:

int n;
printf("&n = %p\n", (void*)&n);

The only cases I can think of where a cast is actually required are
for a conversion between an integer type and a pointer type (not
involving a null pointer constant), or between a pointer-to-function
type and another pointer-to-function type. In both cases, the
conversion is allowed, but it cannot be done implicitly. (Conversion
from one pointer-to-object type to another can be done with two
implicit conversion, one from the source type to void* and another
from void* to the target type. Again, a cast is likely to be
cleaner.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 9 '07 #32

P: n/a
Ben Bacarisse said:
Richard Heathfield <rj*@see.sig.invalidwrites:
>David Tiktin said:
<snip>
>>Are you saying you never actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I don't
know of any occasion where you *need* a cast AND omitting it violates
a constraint or constitutes a syntax error.

Neither do I but what do you do in the recently discussed case of
pointers to pointers to types that lack a qualifier?
I have two answers to this, each based on a different interpretation of
"you".

In the general case (generic "you"), I would answer that, if there is no
escaping the API[1], then perhaps the cast would be the wisest course,
given that you are not changing the type, and you are *adding*
constness rather than taking it away.

In the specific case ("you" as in me), my answer is that I Don't Do
That! :-) That is, I cannot recall ever having to face that problem in
real code, and neither do I anticipate doing so.

<snip>

[1] For example: find the author of f(), and say to him "See this
function? See this keyboard? See this pointy stick?"

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 9 '07 #33

P: n/a
CBFalconer said:
Richard Tobin wrote:
>Richard Heathfield <rj*@see.sig.invalidwrote:
<snip>
>>
>My version, unlike yours, doesn't risk overflow.

And again. Anyway, you have no reason to suppose that "id" can
take values that could cause overflow.

IIRC the id field was declared as an int. Subtracting (or adding)
ints can always create overflows.
To be fair to RT, I think his point was that the problem domain might
not be exposed to that kind of problem - for example, if the values
were all known to be in the range -10000 to +10000. It is impossible to
find two values in that range such that subtracting one from the other
will overflow an int.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 9 '07 #34

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Ben Bacarisse said:
>Richard Heathfield <rj*@see.sig.invalidwrites:
>>David Tiktin said:

<snip>
>>>Are you saying you never actually *need* a cast?

No, there are (rare) occasions when you do need a cast. But I don't
know of any occasion where you *need* a cast AND omitting it violates
a constraint or constitutes a syntax error.

Neither do I but what do you do in the recently discussed case of
pointers to pointers to types that lack a qualifier?

I have two answers to this, each based on a different interpretation of
"you".
I should have said "what do you advice" since the situation came to
mind simply as a counter example to the rather emphatic:

RH3) fix every single diagnostic message, and *never* with a cast
In the general case (generic "you"), I would answer that, if there is no
escaping the API[1], then perhaps the cast would be the wisest course,
given that you are not changing the type, and you are *adding*
constness rather than taking it away.
Of course, hence the example of adding constness.

This may be too big a can of worms to open up, but I would be
interested to know why you consider such double indirect constness
such a bad idea. Is it just that C does not deal with such types
easily and therefore you prefer to avoid them (my only reason for
avoiding them), or is there a more subtle technical reason why some
constness is good while this one is bad?

--
Ben.
Jun 9 '07 #35

P: n/a
Ben Bacarisse said:
Is it just that C does not deal with such types
easily and therefore you prefer to avoid them (my only reason for
avoiding them),
Yes. I'm good at avoiding C features that I don't like. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Jun 9 '07 #36

P: n/a
z wrote:
I use Visual C 2005 to develop my programs. One in particular is
crashing in very specific and hard to replicate situations, made worse
by the fact it only crashes when run -outside- the dev - as an exe,
not from the Debug option. If I try to launch the debug on the
crashing program, it'll close before the debugger opens. Any
suggestions as to how I should proceed? Thanks in advance.
Does it fail when the debug version is run outside the environment, or
is it the release version that fails?
If it is the release version, a possible suggestion is that you actually
can debug the release version as well, but some things might be *very*
strange in the debugger (like freshly assigned variables keeping the old
value and so on because it is not stored to memory yet, understanding of
assembler is a plus in those cases)

To pinpoint an error location outside of the environment could be
possible doing either of those:
for GUI apps:
MessageBox(...);
MessageBeep(...);
for console apps:
printf(...); or fprintf(stderr,...);
(replace ... with proper code...) Of course the first two are very
platform specific.

When all else fail I usually put a pair of those statements in
suspected top level functions, one at the beginning and one at the end
of each function like this:

void somefunction(void)
{
MessageBox("somefunction...","",MB_OK|MB_ICONINFOR MATION);

/* the body of the function */

MessageBox("...somefunction","",MB_OK|MB_ICONINFOR MATION);
}

This obviously won't work well for functions called lots of times unless
they crash fairly fast in program execution.
When a function is pinpointed I put in more message boxes in that
function in key places and so on...

For console apps fprintf(stderr,...) using the same basic technique
could be used instead, I don't know if it would be a good idea to add a
fflush(stderr) to each call... Someone else here could probably answer
that if necessary.
If it just fails strangely and sometimes inside system functions it
might be overwritten memory or some such problem. I use to put
statements like this at key points in my program to find the real reason:
ASSERT(AfxCheckMemory());
(ASSERT only works in debug version however, if you want to do this in
the release version you have to alter the code to some similar)
AfxCheckMemory() is probably very microsoft specific and not at all
portable, but you don't want to keep them there once the problem is
found anyway because they takes some time to execute.

Put one of those lines immediately before the line that crashes the
program. If the ASSERT fails you have a memory corruption problem
somewhere in your program.
If that is the case I put pairs of those in each top level suspected
function. If it crashes on the top one the problem is elsewhere, if it
crashes on the bottom one it is in that function...

If you have multiple threads also it might be a real nightmare to
debug... Try to shut of parts not needed.
Jun 9 '07 #37

P: n/a
In article <i5*********************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>>And again. Anyway, you have no reason to suppose that "id" can
take values that could cause overflow.
>IIRC the id field was declared as an int. Subtracting (or adding)
ints can always create overflows.
>To be fair to RT, I think his point was that the problem domain might
not be exposed to that kind of problem - for example, if the values
were all known to be in the range -10000 to +10000. It is impossible to
find two values in that range such that subtracting one from the other
will overflow an int.
Or, more simply, if you know they're always non-negative.

-- Richard
--
"Consideration shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jun 9 '07 #38

P: n/a
Ian Collins wrote:
Keith Thompson wrote:
>>pete <pf*****@mindspring.comwrites:
>>>Harald van =?UTF-8?B?RMSzaw==?= wrote:

char *strstr(const char *s1, const char *s2)
{

[snip]
>> return (char *)s1;
}

I'd argue that that's a bug in the specification of strstr(), which
IMHO *should* be declared as:

const char *strstr(const char *s1, const char *s2)

I suppose it's declared the way it is to avoid breaking pre-ANSI code
that assigns the result of strstr to an unqualified char* object.
(The const qualifier could safely be added to the parameters without
breaking anything.)
That depends on what you need. If you are passing a non-const array and
plan to modify the array based on the return value, a non-const return
type is appropriate.
<OTThe C++ solution was to provide two versions:

const char *strstr(const char *s1, const char *s2);
char *strstr(char *s1, const char *s2);

</OT>
Yes, these are two separate use cases with regard to qualification of
the parameter and return values. In C, we could do that with two
different function names, but if one works for both, we gain little for
the increased confusion factor.

--
Thad
Jun 9 '07 #39

P: n/a
Thad Smith <Th*******@acm.orgwrites:
Ian Collins wrote:
[...]
><OTThe C++ solution was to provide two versions:
const char *strstr(const char *s1, const char *s2);
char *strstr(char *s1, const char *s2);
</OT>

Yes, these are two separate use cases with regard to qualification of
the parameter and return values. In C, we could do that with two
different function names, but if one works for both, we gain little
for the increased confusion factor.
What we would gain would be const safety. The current inferface
allows constness to be thrown away with no diagnostics from the
compiler. But then as long as string literals aren't const,
maintaining const consistency requires a lot of care by the programmer
anyway.

Probably the strstr() interface was established before the "const"
keyword was added to the language, and adding a second function with a
distinct name was considered too confusing. But we do pay a cost for
the simplicity of having a single function. (If overloading were ever
added to C, splitting the strstr function as C++ did would be a good
idea, but I'm not holding my breath.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 9 '07 #40

P: n/a
Keith Thompson wrote:
Probably the strstr() interface was established before the "const"
keyword was added to the language,
I've never seen a version of strstr
that didn't have a (const char *) type parameter.
and adding a second function with a
distinct name was considered too confusing.
--
pete
Jun 12 '07 #41

P: n/a
pete <pf*****@mindspring.comwrites:
Keith Thompson wrote:
>Probably the strstr() interface was established before the "const"
keyword was added to the language,

I've never seen a version of strstr
that didn't have a (const char *) type parameter.
>and adding a second function with a
distinct name was considered too confusing.
I see that K&R1 doesn't mention strstr, but it does talk about strcat,
strcmp, strcpy, and strlen (and something called strsave, which is
equivalent to strdup, but is presented as an example). This was
before the "const" keyword was added to the language.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 12 '07 #42

This discussion thread is closed

Replies have been disabled for this discussion.