Program crashes when running it outside dev environment

Z

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.
 
M

Morris Dovey

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".
 
Z

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.
 
J

jacob navia

z said:
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.
 
J

jaysome

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
 
J

Joachim Schmitz

z said:
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
 
I

Ian Collins

z said:
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?
 
R

Richard Heathfield

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.
 
T

Tor Rustad

Richard said:
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
 
D

David Tiktin

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
 
R

Richard Heathfield

David Tiktin said:
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.
 
R

Richard Tobin

Harald van Dijk said:
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
 
H

Harald van =?UTF-8?B?RMSzaw==?=

Richard said:
David Tiktin said:


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.
 
D

David Tiktin

David Tiktin said:


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
 
R

Richard Tobin

Richard Heathfield said:
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
 
P

pete

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;
}
 
K

Keith Thompson

David Tiktin said:
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.)
 
R

Richard Heathfield

Harald van D?k said:
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.
 
R

Richard Heathfield

David Tiktin said:
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?
 
R

Richard Heathfield

Richard Tobin said:
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.
 

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
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top