开发者

DO's and Donts while using pointers

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 p开发者_运维百科referred over character array?


C++ specific

  • Avoid manually managing memory, instead use RAII containers such as 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.
  • Indexing arrays is a decent replacement for most pointer arithmetic. It's generally no slower than pointer arithmetic, which is often easier to get wrong and harder to read and maintain. Generally, don't microoptimize at the cost of readability.
  • Call the correct deallocation routine: 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.
  • Explicitly initialize and set meaningless pointers to 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.
  • If you're using C++ inheritance and are overriding the destructor, read up on virtual destructors; these are required for correctness (In short, the base class must have explicitly marked the destructor as virtual).
  • Be aware of who "owns" a pointer if you must manually manage memory. Only the owner should deallocate the object or array the pointer points to, and no other object may use the object after the owner 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.


  1. Always make sure your pointers are initialized
  2. Always know the length of the allocated memory area
  3. Always check for NULL value when working with a pointer
  4. Always delete the pointers after you use them
  5. Never overwrite the memory past the ends of the pointer
  6. Never trust the validity pointers provided to your methods
  7. Never put user input in a pointer (gets for example)
  8. Never mix malloc/free with new/delete
  9. Never allocate pointers to class objects with malloc
  10. Never free class object pointers with free

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

  • Don't point to memory you do not "own".
  • Don't dereference NULL pointers.
  • Do free resources when you don't need them.
  • Don't lose track of your pointers (beware failing reallocs).
  • Don't abuse the void*.
  • Don't mix pointer types: a char* is not the same thing as a double**.
  • Do check the return value of functions that return pointers.


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.


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.


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.


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 .


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.


Don't fail to do bounds checking.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜