Assert and Subscript Checking
Trang 1 trong tổng số 1 trang
Assert and Subscript Checking
Assert and Subscript Checking
Many of the techniques used in writing robust C code also apply in C++. For example, if you have a function that is supposed to be passed a person's name, as a C-style string, it would be wise to say:
#include
void f(char* name)
{
assert(name && *name);
...
}
to perform basic checks on the passed-in pointer. assert() is a function (actually a macro) that checks whether its argument is true (non-zero), and aborts the program if not.
But C++ offers additional opportunities to the designer interested in producing quality code. For example, consider a common problem in C, where vector bounds are not checked during a dereference operation, and a bad location is accessed or written to.
In C++, you can partially solve this problem by defining a Vector class, with a vector dereferencing class member defined for the Vector, and the vector size stored:
#include
#include
class Vector {
int len; // number of elements
int* ptr; // pointer to elements
public:
Vector(int); // constructor
~Vector(); // destructor
int& operator[](int); // dereferencing
};
//constructor
Vector::Vector(int n)
{
assert(n >= 1);
len = n; // store length
ptr = new int[n]; // get storage to store elements
assert(ptr);
}
//destructor
Vector::~Vector()
{
delete ptr;
}
//dereferencing
int& Vector::operator[](int i) {
assert(i >= 1 && i <= len);
return ptr[i - 1]; // return reference to vector slot
}
//driver program
main() {
int i;
const int N = 10;
Vector v(N);
for (i = 1; i <= N; i++) // correct usage
v[i] = i * i;
for (i = 1; i <= N; i++) // correct usage
printf("%d %d\n", i, v[i]);
v[0] = 0; // will trigger assert failure
return 0;
}
In this example, we create a vector of 10 elements, and the vector is indexed 1..10. If the vector is dereferenced illegally, as in:
v[0] = 0;
an assertion failure will be triggered.
One objection to this technique is that it can be slow. If every vector reference requires a function call (to Vector::operator[]), then there may be a large performance hit. However, performance concerns can be dealt with by making the dereferencing function inline.
Two other comments about the above example. We are assuming in these newsletters that if operator new() fails, it returns a NULL pointer:
ptr = new int[n];
assert(ptr); // check for non-NULL pointer
The current draft ANSI standard says that when such a failure occurs, an exception is thrown or else a new handler is invoked. Because many C++ implementations still use the old approach of returning NULL, we will stick with it for now.
The other comment concerns the use of references. In the code:
v[i] = i * i;
the actual code is equivalent to:
v.operator[](i) = i * i;
and could actually be written this way (see a C++ reference book on operator overloading for details).
Vector::operator[] returns a reference, which can be used on the left-hand side of an assignment expression. In C the equivalent code would be more awkward:
Many of the techniques used in writing robust C code also apply in C++. For example, if you have a function that is supposed to be passed a person's name, as a C-style string, it would be wise to say:
#include
void f(char* name)
{
assert(name && *name);
...
}
to perform basic checks on the passed-in pointer. assert() is a function (actually a macro) that checks whether its argument is true (non-zero), and aborts the program if not.
But C++ offers additional opportunities to the designer interested in producing quality code. For example, consider a common problem in C, where vector bounds are not checked during a dereference operation, and a bad location is accessed or written to.
In C++, you can partially solve this problem by defining a Vector class, with a vector dereferencing class member defined for the Vector, and the vector size stored:
#include
#include
class Vector {
int len; // number of elements
int* ptr; // pointer to elements
public:
Vector(int); // constructor
~Vector(); // destructor
int& operator[](int); // dereferencing
};
//constructor
Vector::Vector(int n)
{
assert(n >= 1);
len = n; // store length
ptr = new int[n]; // get storage to store elements
assert(ptr);
}
//destructor
Vector::~Vector()
{
delete ptr;
}
//dereferencing
int& Vector::operator[](int i) {
assert(i >= 1 && i <= len);
return ptr[i - 1]; // return reference to vector slot
}
//driver program
main() {
int i;
const int N = 10;
Vector v(N);
for (i = 1; i <= N; i++) // correct usage
v[i] = i * i;
for (i = 1; i <= N; i++) // correct usage
printf("%d %d\n", i, v[i]);
v[0] = 0; // will trigger assert failure
return 0;
}
In this example, we create a vector of 10 elements, and the vector is indexed 1..10. If the vector is dereferenced illegally, as in:
v[0] = 0;
an assertion failure will be triggered.
One objection to this technique is that it can be slow. If every vector reference requires a function call (to Vector::operator[]), then there may be a large performance hit. However, performance concerns can be dealt with by making the dereferencing function inline.
Two other comments about the above example. We are assuming in these newsletters that if operator new() fails, it returns a NULL pointer:
ptr = new int[n];
assert(ptr); // check for non-NULL pointer
The current draft ANSI standard says that when such a failure occurs, an exception is thrown or else a new handler is invoked. Because many C++ implementations still use the old approach of returning NULL, we will stick with it for now.
The other comment concerns the use of references. In the code:
v[i] = i * i;
the actual code is equivalent to:
v.operator[](i) = i * i;
and could actually be written this way (see a C++ reference book on operator overloading for details).
Vector::operator[] returns a reference, which can be used on the left-hand side of an assignment expression. In C the equivalent code would be more awkward:
- Code:
#include <stdio.h>
int x[10]; // use f() to index into x[10]
int* f(int i) {
return &x[i - 1];
}
main() {
*f(5) = 37;
printf("%d %d\n", *f(5), x[4]);
return 0;
}
Trang 1 trong tổng số 1 trang
Permissions in this forum:
Bạn không có quyền trả lời bài viết