C++ Without Memory Errors

原创 2002年02月26日 08:56:00

C++ Without Memory Errors

by Dejan Jelović

Here are the slides and the code from a recent talk I've given on writing C++ programs without memory errors.

An article with more details will be ready soon.


Memory errors are the worst kind of errors in C and C++. They are hard to reproduce and thus hard to debug. Have you ever used a non-trivial C or C++ program that never crashed?


I've been programming in Java for the last year. In Java one sees almost no hard to reproduce problems. Why is that?


Is it because Java is a safer language? No. Java makes you use too many casts and lacks support for types with value semantics. It doesn't have destructors so resource management is really hard. It is less safe than C++.


The real reason is garbage collection.


How does garbage collection help? Does it free us from freeing memory? Not really. Try implementing a Vector in Java and you will see how easy it is to forget to set a reference to null, thus leaking memory.


The benefit of garbage collection is this: it guarantees that a pointer will either point to a valid allocated object or be null.


Think about it: if a pointer is either valid or null, there can be no weird memory errors.


How do we do that in C++?


How about adding garbage collection to C++? A company named Geodesic claims their garbage collector for C++ works great.


Garbage collection helps, but it is not enough. We still have to call the destructors manually, and to remember to set pointers to NULL. That's too much room for error.

There is also a performance penalty. Programs with garbage collection use 50% more memory than programs with manual memory management. That translates into much slower execution because it increases the chances of memory being swapping out to disk.


Here's the solution: Use a smart pointer.


What would be the characteristics of such a smart pointer?

  1. It always points either to a valid allocated object or is NULL.
  2. It deletes the object once there are no more references to it.
  3. It can be used with existing code.
  4. Programs that don’t do low-level stuff can be written exclusively using this pointer. Native pointers don’t have to be used at all.
  5. Native pointers can be converted into smart pointers via a special construct. It should be easy to search for this construct using grep since it is unsafe.
  6. Thread-safe.
  7. Exception safe.
  8. Fast. It should have zero dereferencing overhead and minimal manipulation overhead.
  9. It shouldn’t have problems with circular references.

If we disregard the requirement #9, then it's easy. Simply have a smart pointer that is made out of two native pointers. One points to the real object, the other to the reference count:

A diagram in which each smart pointer points to the object with one native pointer and to the reference count with the other native pointer.


We also provide a template function called create that creates a new object using the operator new and then returns a smart pointer. That guarantees that the smart pointer is valid.


We also provide a back door to ease the transition. There is a wrapPtr function that takes a native pointer and makes a smart pointer. This is unsafe. So we didn't use a constructor, but a special function that is easy to search for if you have any problems.


This leaves us with the problem of circular references.


Circular references and reference counting don't go well together. Maybe we can find a simpler problem?


In real-world programs you almost never have real cyclic data structures. Usually you have hierarchies, like the window hierarchy or a directory tree:

a tree made out of nodes in which parents point to children and children point to parents


The problem with a reference counting and hierarchies is that a parent points to a child, and a child points to the parent. Hence they both have a reference count of one, and are never deleted.


People that use reference-counted pointers usually find a way out of this mess by using a native pointer from the child to the parent.

But this is not a good solution, because we are trying not to use native pointers. We want pointers that are either pointing to a valid object or are null.


Here's a solution: we need weak smart pointers!

They will be just like regular reference counter pointers, only their references won't count. If you have a "strong" pointer and a weak pointer pointing to the same object, and the strong pointer is destroyed, the weak pointer immediately becomes null.


How do we implement this? We keep two reference counts: One for total number of pointers, and one for strong pointers.

When dereferencing a weak pointer, we check the strong reference count. If it is zero, we return NULL.


Try it out! The code is right here: SafePtr.zip.

The code is done using the Intel C++ compiler for the Windows platform.

You need a compiler that can handle templates correctly. Visual C++ (version 6, service pack 4) chokes on them and either silently makes a compilation error or gives an internal compiler error.

If you are not using Windows you will need to modify the SmartPtr.h file. It uses the Windows API function InterlockedIncrement and InterlockedDecrement to modify the reference count. These functions are nothing more than a thread-safe way to increment and decrement a long. Each OS or compiler should have the equivalents, you just have to find them.


There are three files in the archive:

safeptr.h - this is the one that you need to include in order to use the smart pointers; everything is in the namespace named 'safe'.

test.cpp - this is a program that puts the smart pointer through the hoops

demo.cpp - look at this one if you want to learn how to use the library

 

Read more...


Content of this site is © Dejan Jelovic. All rights reserved.

在ICC中编译过程出现:):[warning] calling a function without prototype may cause runtime erro

在ICC中写程序 编译过程中出现如下警告 :[warning] calling a function without prototype may cause runtime errors if the...
  • xiayufeng520
  • xiayufeng520
  • 2012年08月22日 08:39
  • 1707

内存一致性错误(Memory Consistency Errors)

内存一致性错误发生在当不同的线程本对相同数据有不一致的视角。造成内存一致性错误的原因很复杂,不在本教程的范围之内。幸运的是,程序员不需要了解造成这个问题的详细原因,所需要的是一个策略来避免它们的发生。...
  • rjcs888
  • rjcs888
  • 2016年07月03日 23:25
  • 401

phpmyadmin出现“Cannot start session without errors, please check errors given in your PHP and/or webs”

phpmyadmin出现“Cannot start session without errors, please check errors given in your PHP and/or webse...
  • binsoft
  • binsoft
  • 2015年01月13日 15:50
  • 867

spring mvc报: Errors/BindingResult argument declared without preceding model attribute

spring mvc报: Errors/BindingResult argument declared without preceding model attribute. 是因为在spring m...
  • okey88
  • okey88
  • 2012年10月25日 18:00
  • 5233

phpMyAdmin "Cannot start session without errors"

phpMyAdmin "Cannot start session without errors" 这个问题目前已经解决,但是有点搞笑: 是这样的,如果将项目放到远程服务器,那么数据...
  • magicbreaker
  • magicbreaker
  • 2013年04月13日 17:10
  • 2545

Cannot start session without errors, please check errors given in your PHP and/or webserver log file and configure your PHP inst

Cannot start session without errors, please check errors given in your PHP and/or webserver log file...
  • RoyYeah
  • RoyYeah
  • 2009年09月07日 21:05
  • 7770

Debugging Memory Errors in C/C++

Debugging Memory Errors in C/C++ http://scottmcpeak.com/memory-errors/ This page describes a f...
  • fzh90
  • fzh90
  • 2014年06月20日 21:37
  • 688

TI C6000 系列 DSP 之 CCS5.2 编译时报错: #10010 和 #10264

----------------------------------------------------------------------------------------------------...
  • KISSMonX
  • KISSMonX
  • 2013年01月04日 09:52
  • 7223

23 查询数据

24  查询数据 本主题提供有关在Greenplum的数据库使用SQL的信息。 你进入所谓的查询中使用PSQI交互式SQL客户端和其他客户端工具的数据库查看,更改和分析数据的SQL语句。 •     ...
  • kygoal
  • kygoal
  • 2017年07月25日 23:25
  • 213

phpMyAdmin - Error Cannot start session without errors, please check errors given in your PHP and/or

phpmyadmin 出现Cannot start session without errors 错误 总结的几种原因和解决办法 原来服务器上装的phpmyadmin好好的,后来因有个网站被...
  • jaray
  • jaray
  • 2014年06月11日 17:31
  • 1132
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Without Memory Errors
举报原因:
原因补充:

(最多只允许输入30个字)