Simple C++ program crash - why?

M

Mathew McBride

Hello all,
I'm a self-taught java dev trying to teach (yet again) teach myself the
ins-n-outs of C++. I'm working on the problem from
http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/INTRODUCTION.html#youTry3

I haven't gotten far in figuring out the reason why my program crashes.
I've tried on three different platforms (cygwin, opensolaris and linux)
but can't squeeze a decent stack trace out of gdb (yes, using g++ -g -O0).

It happens after cout (i.e the last thing my program does), and some
stack traces I've got indicate a problem with ~Address - does this
indicate some sort of destructor for a stack like there are in classes?

Heres the source:
#import <iostream>
struct Address {
std::string city;
int zip;
};

struct Student {
int id;
bool isGrad;
Address addr;
};
int numOfGrads (Student std[], int nstd);
int main(int nargs, char *args[]) {
Student students[1];
students[0].id = 0;
students[0].isGrad = true;
students[0].addr.city = "Geelong";
students[0].addr.zip = 3200;
students[1].id = 1;
students[1].isGrad = false;
students[1].addr.city = "Werribee";
students[1].addr.zip = 7331;
int gr = numOfGrads(students, 1);
std::cout << "Number of students is: " << gr << std::endl;
return 0;
}
int numOfGrads(Student std[], int nstd) {
int num = 0;
int x;
for (x=0; x<nstd; x++) {
if (std[x].isGrad) {
num++;
}
}
return num;
}
 
J

Jerry Coffin

[ ... ]
int main(int nargs, char *args[]) {
Student students[1];

This defines an array of _one_ and only one student.
students[0].id = 0; [ ... ]
students[1].id = 1;

Here you're accessing not just one, but _two_ students in the array. The
result is undefined behavior.

My advice would be to ignore the fact that there IS such a thing as an
array in C++. Using std::vector can virtually eliminate problems like
this.
 
K

Kai-Uwe Bux

Mathew said:
Hello all,
I'm a self-taught java dev trying to teach (yet again) teach myself the
ins-n-outs of C++. I'm working on the problem from
http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/INTRODUCTION.html#youTry3

I haven't gotten far in figuring out the reason why my program crashes.
I've tried on three different platforms (cygwin, opensolaris and linux)
but can't squeeze a decent stack trace out of gdb (yes, using g++ -g -O0).

It happens after cout (i.e the last thing my program does), and some
stack traces I've got indicate a problem with ~Address - does this
indicate some sort of destructor for a stack like there are in classes?

Heres the source:
#import <iostream>

#include is standard.
#import is an extension.
struct Address {
std::string city;
int zip;
};

struct Student {
int id;
bool isGrad;
Address addr;
};
int numOfGrads (Student std[], int nstd);
int main(int nargs, char *args[]) {
Student students[1];

You have two students. Hence, you want:

Student students [2];
students[0].id = 0;
students[0].isGrad = true;
students[0].addr.city = "Geelong";
students[0].addr.zip = 3200;
students[1].id = 1;
students[1].isGrad = false;
students[1].addr.city = "Werribee";
students[1].addr.zip = 7331;
int gr = numOfGrads(students, 1);
std::cout << "Number of students is: " << gr << std::endl;
return 0;
}
int numOfGrads(Student std[], int nstd) {
int num = 0;
int x;
for (x=0; x<nstd; x++) {
if (std[x].isGrad) {
num++;
}
}
return num;
}

Suggestions:

a) You want to ditch arrays for std::vector or std::deque.
b) You want to make numOfGrads() an algorithm that works on iterators.
c) You want to have a look at std::count_if() and boost::lamba.


Best

Kai-Uwe Bux
 
M

Mathew McBride

*bangs head on wall, multiple times*
yeah thanks, re #import, I've also done objc so I'm confusing myself.
Thanks Jerry and Kai.
Kai-Uwe Bux said:
Mathew said:
Hello all,
I'm a self-taught java dev trying to teach (yet again) teach myself the
ins-n-outs of C++. I'm working on the problem from
http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/INTRODUCTION.html#youTry3
I haven't gotten far in figuring out the reason why my program crashes.
I've tried on three different platforms (cygwin, opensolaris and linux)
but can't squeeze a decent stack trace out of gdb (yes, using g++ -g -O0).

It happens after cout (i.e the last thing my program does), and some
stack traces I've got indicate a problem with ~Address - does this
indicate some sort of destructor for a stack like there are in classes?

Heres the source:
#import <iostream>

#include is standard.
#import is an extension.
struct Address {
std::string city;
int zip;
};

struct Student {
int id;
bool isGrad;
Address addr;
};
int numOfGrads (Student std[], int nstd);
int main(int nargs, char *args[]) {
Student students[1];

You have two students. Hence, you want:

Student students [2];
students[0].id = 0;
students[0].isGrad = true;
students[0].addr.city = "Geelong";
students[0].addr.zip = 3200;
students[1].id = 1;
students[1].isGrad = false;
students[1].addr.city = "Werribee";
students[1].addr.zip = 7331;
int gr = numOfGrads(students, 1);
std::cout << "Number of students is: " << gr << std::endl;
return 0;
}
int numOfGrads(Student std[], int nstd) {
int num = 0;
int x;
for (x=0; x<nstd; x++) {
if (std[x].isGrad) {
num++;
}
}
return num;
}

Suggestions:

a) You want to ditch arrays for std::vector or std::deque.
b) You want to make numOfGrads() an algorithm that works on iterators.
c) You want to have a look at std::count_if() and boost::lamba.


Best

Kai-Uwe Bux
 
J

Juha Nieminen

Jerry said:
This defines an array of _one_ and only one student.
students[0].id = 0; [ ... ]
students[1].id = 1;

Here you're accessing not just one, but _two_ students in the array. The
result is undefined behavior.

My advice would be to ignore the fact that there IS such a thing as an
array in C++. Using std::vector can virtually eliminate problems like
this.

Exactly how does std::vector prevent you from indexing out of bounds
with the [] operator?
 
K

Kai-Uwe Bux

Juha said:
Jerry said:
This defines an array of _one_ and only one student.
students[0].id = 0; [ ... ]
students[1].id = 1;

Here you're accessing not just one, but _two_ students in the array. The
result is undefined behavior.

My advice would be to ignore the fact that there IS such a thing as an
array in C++. Using std::vector can virtually eliminate problems like
this.

Exactly how does std::vector prevent you from indexing out of bounds
with the [] operator?

Note that you are not paraphrasing the claim.

It does not _prevent_ you from doing so. However, it _encourages_ the use of
begin() and end(). Moreover, the original interface was something like

int numOfGrads(Student std[], int nstd)

where it is up to the programmer to remember the size of the array
correctly. With std::vector, you have the size() method and the interface
would just be

unsigned int numOfGrads( std::vector< Student > const & s_vec );

Also, as a quality of implementation issue, I came to expect an assert or
something similar which I can turn on/off inside operator[] so that
mistakes such as the one you point out are easily caught.


But again, nothing _prevents_ you from running into undefined behavior.
Nonetheless, the usual problems (as shown in, e.g., the original post) by
and large disappear with the adoption of std::vector<> and the idioms that
come with it.


Best

Kai-Uwe Bux
 
J

Jerry Coffin

Jerry said:
This defines an array of _one_ and only one student.
students[0].id = 0; [ ... ]
students[1].id = 1;

Here you're accessing not just one, but _two_ students in the array. The
result is undefined behavior.

My advice would be to ignore the fact that there IS such a thing as an
array in C++. Using std::vector can virtually eliminate problems like
this.

Exactly how does std::vector prevent you from indexing out of bounds
with the [] operator?

By itself, it doesn't. Nonetheless, indexing out of bounds virtually
disappears anyway. In this case, he defined an array of a given size,
and then indexed into it. In the case of vector, you typically define it
empty, and then use push_back to add items -- and it automatically
allocates more memory as needed. Likewise, he passed a pointer and a
size -- but, again, with vector you don't normally do that. Rather, you
just pass the vector, which knows its size. Finally, with vector you can
often avoid using indexing at all -- you use an algorithm, and pass the
results from begin() and end() to the algorithm as the bounds on what
it's going to work with. This, again, essentially removes the
possibility of generating an index that's out of bounds to start with.
 

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

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top