Snipe hunting in C++

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

I just spent the better part of two hours trying to find a problem with my
code. The error messages had virtually nothing to do with the actual
problem. The problem, as it turned out, was a missing "}" to close a
namespace in a file I had moved from one namespace to another. This isn't
the first time something like this has happened. I guess after some time
I'll get better at knowing how to isolate such problems.

The worst thing about situations like this is that I start changing code to
see if it will correct the problem. That can introduce other problems that
persist after the original problems is identified and corrected. Do other
people run into situations like this?

To me, this is the hard part about working with C++. I can understand the
concepts of the language fairly well. I just waste a lot of time hunting
snipes.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
S

Steven T. Hatton

Lieven wrote:

For this specific problem, whenever I open a {, I immediately close it.
Like:

void function(){}

and then I start filling in the body. It really helps avoiding such
errors.

I do that when I create a namespace or a class. Especially when it comes to
classes I find it best to be sure I put the ';' at the end before I do
anything else. In the case I just described in my previous post, I was
refactoring, so the class and namespace already existed. I really thought
I had put the '}' at the end when I changed things. Perhaps I
inadvertently deleted it before I saved the file.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
D

David Lindauer

Lieven said:
For this specific problem, whenever I open a {, I immediately close it.
Like:

void function(){}

and then I start filling in the body. It really helps avoiding such errors.

he said he was in the middle of a code maintenance op tho... and it is *easy* to
get into such situations during maintanence.

David
 
S

Steven T. Hatton

filo said:
You could use vi with syntax coloring.
I'm currently using Emacs with font-lock-mode. Sure, it helps _a_lot_, but
it didn't help much in finding the problem. One main reason it was hard to
find was that the errors were pointing to other files that directly or
indirectly included the problematic file.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
E

E. Robert Tisdale

Steven said:
I just spent the better part of two hours trying to find a problem with my code.
The error messages had virtually nothing to do with the actual problem.
The problem, as it turned out, was a missing "}"

This is a flaw in the language design inherited from C.
Common lisp has a similar problem with parentheses.
The problem is that
the the bracket pairs (curly, square, angle) or parentheses
are almost invisible to the human eye.
Other languages use more visible 'begin' and 'end' keywords.
You might consider defining C preprocessor macros:

#define begin {
#define end }

and using them instead of brackets.

Misuse of the C style comment "brackets" '/*' and '*/"
also can introduce bugs that are extremely hard to track down.
to close a namespace in a file I had moved from one namespace to another.
This isn't the first time something like this has happened.
I guess [that] after some time
I'll get better at knowing how to isolate such problems.

Unfortunately, no.
Bugs introduced by typo's and paste-o's cause everyone grief.
The worst thing about situations like this is that I start changing code to
see if it will correct the problem. That can introduce other problems
that persist after the original problems is identified and corrected.
Do other people run into situations like this?

Have you considered using some sort of revision control system?

https://www.cvshome.org/
To me, this is the hard part about working with C++.
I can understand the concepts of the language fairly well.
I just waste a lot of time hunting snipes.

Being anal about a consistent style seems to help a little.
You can easily spot small departures
from the way you usually write code
and sometimes those departures are subtle bugs.
 
J

Jonathan Turkanis

Steven T. Hatton said:
I just spent the better part of two hours trying to find a problem with my
code. The error messages had virtually nothing to do with the actual
problem. The problem, as it turned out, was a missing "}" to close a
namespace in a file I had moved from one namespace to another. This isn't
the first time something like this has happened. I guess after some time
I'll get better at knowing how to isolate such problems.

This is definitely a familiar problem. I know that on my main compiler (VC7.1)
the error messages generated when there is a missing "}" give little indication
of what the real problem is. But after much experience writing ill-formed code
I've learned what these error messages look like, so I now start looking for the
missing "}" immediately.
The worst thing about situations like this is that I start changing code to
see if it will correct the problem. That can introduce other problems that
persist after the original problems is identified and corrected. Do other
people run into situations like this?

Just back everything up right before you know you are about to make a series of
major changes to track down the location of the missing "}". One you find it,
revert to the saved version and apply the change.

Jonathan
 
J

Jonathan Turkanis

E. Robert Tisdale said:
You might consider defining C preprocessor macros:

#define begin {
#define end }

This is funny. Think of what it would do to code using the STL.

Jonathan
 
K

Karthik Kumar

Jonathan said:
Okay.

Program text:

#include <vector>

#define begin {
#define end }

int main()
{
using namespace std;
vector<char> v(10, 'a');
for ( vector<char>::iterator first = v.begin(), last = v.end();
first != last;
++first )
{
*first = 'b';
}

}

Preprocessed output:

<snip>

int main()
{
using namespace std;
vector<char> v(10, 'a');
for ( vector<char>::iterator first = v.{(), last = v.}();
first != last;
++first )
{
*first = 'b';
}
}

Jonathan

Funny :) .
A very good counter-example to prove why macros always ought to be in
*all caps*.
 
J

Jonathan Turkanis

E. Robert Tisdale said:

Okay.

Program text:

#include <vector>

#define begin {
#define end }

int main()
{
using namespace std;
vector<char> v(10, 'a');
for ( vector<char>::iterator first = v.begin(), last = v.end();
first != last;
++first )
{
*first = 'b';
}

}

Preprocessed output:

<snip>

int main()
{
using namespace std;
vector<char> v(10, 'a');
for ( vector<char>::iterator first = v.{(), last = v.}();
first != last;
++first )
{
*first = 'b';
}
}

Jonathan
 
L

Lieven

Steven said:
I just spent the better part of two hours trying to find a problem with my
code. The error messages had virtually nothing to do with the actual
problem. The problem, as it turned out, was a missing "}" to close a
namespace in a file I had moved from one namespace to another. This isn't
the first time something like this has happened. I guess after some time
I'll get better at knowing how to isolate such problems.

The worst thing about situations like this is that I start changing code
to
see if it will correct the problem. That can introduce other problems
that
persist after the original problems is identified and corrected. Do other
people run into situations like this?

To me, this is the hard part about working with C++. I can understand the
concepts of the language fairly well. I just waste a lot of time hunting
snipes.

For this specific problem, whenever I open a {, I immediately close it.
Like:

void function(){}

and then I start filling in the body. It really helps avoiding such errors.
 
M

Marcelo Pinto

Jonathan Turkanis said:
Just back everything up right before you know you are about to make a series > of
major changes to track down the location of the missing "}". One you find it,
revert to the saved version and apply the change.

Jonathan

Better. Use some kind of version control system.

Marcelo Pinto
 
E

E. Robert Tisdale

Jonathan Turkanis wrote:

[snip]
cat main.cc
#include <vector>

#define BEGIN {
#define END }

int main(int argc, char* argv[])
BEGIN
using namespace std;
vector<char> v(10, 'a');
for (vector<char>::iterator i = v.begin(); i != v.end(); ++i)
BEGIN
*i = 'b';
END
return 0;
END
 
J

Jonathan Turkanis

E. Robert Tisdale said:
Jonathan Turkanis wrote:

[snip]
cat main.cc
#include <vector>

#define BEGIN {
#define END }

int main(int argc, char* argv[])
BEGIN
using namespace std;
vector<char> v(10, 'a');
for (vector<char>::iterator i = v.begin(); i != v.end(); ++i)
BEGIN
*i = 'b';
END
return 0;
END

All caps is a must, but you also need a unique 'namespace' prefix. Furthermore,
while you're at it, you should correct some other language flaws. May I suggest

#include <vector>

#define PUNC_BEGIN_CURLY {
#define PUNC_END_CURLY }
#define PUNC_BEGIN_ROUND {
#define PUNC_END_ROUND }
#define PUNC_BEGIN_SQUARE {
#define PUNC_END_SQUARE }
#define PUNC_BEGIN_ANGLED {
#define PUNC_END_ANGLED }

int main
PUNC_BEGIN_ROUND
int argc, char* argv PUNC_BEGIN_SQUARE PUNC_END_SQUARE
PUNC_END_ROUND
PUNC_BEGIN_CURLY
using namespace std;
vector PUNC_BEGIN_ANGLED char PUNC_END_ANGLED v
PUNC_BEGIN_ROUND
10, 'a'
PUNC_END_ROUND;
for
PUNC_BEGIN_ROUND
vector PUNC_BEGIN_ANGLED char PUNC_END_ANGLED::iterator
i = v.begin PUNC_BEGIN_ROUND PUNC_END_ROUND;
i != v.end PUNC_BEGIN_ROUND PUNC_END_ROUND;
++i
PUNC_END_ROUND
PUNC_BEGIN_CURLY
*i = 'b';
PUNC_END_CURLY
return 0;
PUNC_END_CURLY

Jonathan
 
M

Mike Wahler

Jonathan Turkanis said:
#include <vector>

#define PUNC_BEGIN_CURLY {
#define PUNC_END_CURLY }
#define PUNC_BEGIN_ROUND {
#define PUNC_END_ROUND }
#define PUNC_BEGIN_SQUARE {
#define PUNC_END_SQUARE }
#define PUNC_BEGIN_ANGLED {
#define PUNC_END_ANGLED }

int main
PUNC_BEGIN_ROUND
int argc, char* argv PUNC_BEGIN_SQUARE PUNC_END_SQUARE
PUNC_END_ROUND
PUNC_BEGIN_CURLY
using namespace std;
vector PUNC_BEGIN_ANGLED char PUNC_END_ANGLED v
PUNC_BEGIN_ROUND
10, 'a'
PUNC_END_ROUND;
for
PUNC_BEGIN_ROUND
vector PUNC_BEGIN_ANGLED char PUNC_END_ANGLED::iterator
i = v.begin PUNC_BEGIN_ROUND PUNC_END_ROUND;
i != v.end PUNC_BEGIN_ROUND PUNC_END_ROUND;
++i
PUNC_END_ROUND
PUNC_BEGIN_CURLY
*i = 'b';
PUNC_END_CURLY
return 0;
PUNC_END_CURLY

Jonathan

Have I died and gone to COBOL? :)

-Mike
 
E

E. Robert Tisdale

Jonathan Turkanis wrote:

[snip]
cat main.cc
#include <vector>

#define BEGIN {
#define END }
#define FOR for (
#define DO )

int main(int argc, char* argv[]) BEGIN
using namespace std;
vector<char> v(10, 'a');
FOR vector<char>::iterator i = v.begin(); i != v.end(); ++i DO
BEGIN
*i = 'b';
END
return 0;
END
 
S

Steven T. Hatton

E. Robert Tisdale said:
This is a flaw in the language design inherited from C.
Common lisp has a similar problem with parentheses.
The problem is that
the the bracket pairs (curly, square, angle) or parentheses
are almost invisible to the human eye.
Other languages use more visible 'begin' and 'end' keywords.
You might consider defining C preprocessor macros:

#define begin {
#define end }

and using them instead of brackets.

That really would have done little in this case. What helped was C-x C-h
C-M-\, and then scrolling to the end of the file.
Misuse of the C style comment "brackets" '/*' and '*/"
also can introduce bugs that are extremely hard to track down.

Fortunately, font-lock-mode catches those for me.
to close a namespace in a file I had moved from one namespace to another.
This isn't the first time something like this has happened.
I guess [that] after some time
I'll get better at knowing how to isolate such problems.

Unfortunately, no.
Bugs introduced by typo's and paste-o's cause everyone grief.
The worst thing about situations like this is that I start changing code
to
see if it will correct the problem. That can introduce other problems
that persist after the original problems is identified and corrected.
Do other people run into situations like this?

Have you considered using some sort of revision control system?

https://www.cvshome.org/
That's only marginally helpful. First off, I need to be sure I make the
appropriate adds and commits before I introduce such a bug. Even if I do,
I am then required to pick through what I subsequently did to identify the
changes I really didn't want. If I leave all my files open while hunting
such a bug, then I can roll them back with C-M-_. But it's still a pain.
Being anal about a consistent style seems to help a little.
You can easily spot small departures
from the way you usually write code
and sometimes those departures are subtle bugs.

And that makes switching between editors a real pain. I depend on the hard
indentation in Emacs. Other editors my simulate such a feature in one way
or another, but usually with some adverse consequence.
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 

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,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top