Its a simple but important question. What are the do's and donts while using a pointers in C and C++ so as to make sure SEGMENTATION FAULT is avoided on AIX?
Where char * are preferred over character array?
Its a simple but important question. What are the do's and donts while using a pointers in C and C++ so as to make sure SEGMENTATION FAULT is avoided on AIX?
Where char * are preferred over character array?
Write standard compliant code. That should take care of the platform. And a lot of other issues. And use const
. That takes care of more issues.
And last but not least
Never use pointers unless you have to... There are (const) references to avoid copy construction of objects passed to functions and STL containers and strings for the other storage requirements and use smart (boost::shared_ptr) pointers if you really need pointers and don't want to track them by hand.
In C
void*
.char*
is not the same thing as a double**
.std::auto_ptr
, boost::scoped_ptr
, boost::shared_ptr
and the equivalent array containers. Even simpler, often std::vector
works just fine, and it doesn't require any pointer usage at all. Finally, instead of passing pointers to large or modifiable data structures, you can pass references. Pointers can represent arrays, whereas references avoid that ambiguity.delete[]
is for arrays allocated via new ...[]
only, delete
for pointers to single objects only, and free(...)
only for memory allocated via the C api (such as malloc(..)
). These must not be confused; C++ deallocation routines include destructor calls and are thus required to be called correctly.NULL
. It's easier to debug an accidental null dereference than an incorrect memory access. It's OK to deallocate the NULL
pointer, so you don't need to clutter your destructor with checks to avoid this. If you delete
an object prematurely, you should thus set its pointer to NULL
to avoid double-deleting the same pointer and to avoid accidentally dereferencing a dangling pointer.delete
's the pointer to it. boost::shared_ptr
is a hassle-free fairly low overhead container which is often fine when you do need to share a pointer.I joined some time ago a project where a few good developers used only bare pointers. Even though their have excellent skills their program (run on Windows/Linux/HP-UX) from time to time caused segfaults and there were a few memory leaks.
I understand that if a program is quite big and has threads it's very difficult to find all bugs related to pointers and unless you absolutely need a bare pointer you should use Boost.Smart_ptr .
In C++ always use virtual destructors. If you delete base class, this will ensure that destuctor of derived class is called. If you don't do this and derived class did some allocations, you will not have a chance to clean it up.
The ownership question is often the hardest one: your design should already decide on that. The one owning the object should be responsible for destroying it.
But I've seen scenario's where destructed objects were still referred to, too - aka dangling pointers. Your design should take the "validity" into account, too. Every reference to a deleted object should be noticeably invalid. If I'm not mistaken, the weak_ptr
class can postpone this decision.
NOTE: C specific answer->
Following are the common causes of this segmentation violation or segmentation fault:
Improper format control string in printf or scanf statements: Make sure the format control string has the same number of conversion specifiers (%'s) as the printf or scanf has arguments to be printed or read, respectively, and that the specifiers match the type of variable to be printed or read. This also applies to fprintf and fscanf.
Forgetting to use "&" on the arguments to scanf: Function scanf takes as arguments the format control string and the addresses of variables in which it will place the data that it reads in. The "&" (address of) operator is used to supply the address of a variable. It is common to forget to use "&" with each variable in a scanf call. Omitting the "&" can cause a segmentation violation.
Accessing beyond the bounds of an array: Make sure that you have not violated the bounds of any array you are using; i.e., you have not subscripted the array with a value less than the index of its lowest element or greater than the index of its highest element.
Failure to initialize a pointer before accessing it: A pointer variable must be assigned a valid address (i.e., appear on the left-hand-side of an assignment) before being accessed (i.e., appearing on the right-hand-side of an assignment). Make sure that you have initialized all pointers to point to a valid area of memory. Proper pointer initialization can be done several ways. Examples are listed below.
Incorrect use of the "&" (address of) and "" (dereferencing) operators: Make sure you understand how these operators work. Know when they should be applied and when not to apply them. As mentioned above, it is common to forget to use "&" with each variable in a scanf call. Remember, scanf requires the address of the variables it is reading in. Especially, know when "&" and "" are absolutely necessary and when it is better to avoid using them.
Troubleshooting the problem:
Check EVERY place in your program that uses pointers, subscripts an array, or uses the address operator (&) and the dereferencing operator (*). Each is a candidate for being the cause of a segmentation violation. Make sure that you understand the use of pointers and the related operators. If the program uses many pointers and has many occurrences of & and *, then add some printf statements to pinpoint the place at which the program causes the error and investigate the pointers and variables involved in that statement.
Remember that printf statements for debugging purposes should have a new-line character (\n) at the end of their format control strings to force flushing of the print buffer.
Not really an answer to the "Where char * are preferred over character array?" question, but one thing that recently bit someone I was reviewing was "sizeof".
Consider this:
char *a = new char[3];
char b[3];
In many places you use the "a" and "b" in similar ways. The problems start when you do something like:
strncpy(b, some_string, sizeof(b));
strncpy(a, some_string, sizeof(a));
I guess the moral of the story is: Be careful with sizeof(). It's probably better to keep a size constant around.