Change your MSDscript implementation to use std::shared_ptr
so that it doesn't leak memory when interpreting programs.
You should use these macros to make your code more readable and to help with the transition:
#ifndef __msdscript_pointer__
#define __msdscript_pointer__
#include <memory>
#define USE_PLAIN_POINTERS 1
#if USE_PLAIN_POINTERS
# define NEW(T) new T
# define PTR(T) T*
# define CAST(T) dynamic_cast<T*>
# define CLASS(T) class T
# define THIS this
#else
# define NEW(T) std::make_shared<T>
# define PTR(T) std::shared_ptr<T>
# define CAST(T) std::dynamic_pointer_cast<T>
# define CLASS(T) class T : public std::enable_shared_from_this<T>
# define THIS shared_from_this()
#endif
#endif
Put that code in a new header file, perhaps pointer.h
. You will need to #include "pointer.h"
in any header file before it uses the PTR
macro or any of the other macros. The #ifdef
...#endif
pattern that wraps the code above makes it ok to include pointer.h
multiple times — which will happen when, say, a file has #include "expr.h"
and #include "val.h"
and both expr.h
and val.h
contain #include "pointer.h"
.
After you have made the refactorings to use theses macros as shown in the videos and slides, then you'll be able to change the definition of USE_PLAIN_POINTERS
. After that, using leaks
to check your MSDscript implementation (when it runs an MSDscript program) will not report any leaks.
This refactoring amounts to just a search and replace, and you could perform the change without really understanding what it does. However, if you make a mistake or miss a step somewhere, then you're likely to get verbose messages from the C++ compiler; it will help to have at least some idea of what the change is doing to decode those messages. Unfortunately, your programming environment's refactoring tools probably will not be much help for this search-and-replace change. Still, a pattern-based search-and-replace will work much better than a plain search-and-replace, so explore that option in your environment if you haven't used it before.
After you convert to std::shared_ptr
, you may see warnings from the compiler about “virtual destructors.” To get rid of those warnings, add virtual ~T() { }
in the declaration of each base class T
— so virtual ~Expr() { }
in Expr
, and so on. You won't need to add that to derived subclasses.
Some problems to avoid:
Expr
and Val
classes to use CLASS
. Do not change a class
to CLASS
in a declaration that has something like : public Expr
to declare a superclass.THIS
as an instance of a derived class instead of the superclass (say, NumVal
instead of Val
), you may need to use a combination of CAST
and THIS
.