问:
Should the Vector type inherit from the Array type in an environment where both are first-class objects
I have created a programming language that is based on java for a personal project. The language already has generic classes and functions and the generics are completely compatible with primitive types (which I decided not to turn into objects, autoboxed or otherwise).

I am currently designing the Standard Library and having never created a Standard Library I am not sure if making the Vector type inherit from Array would be a disaster or not. Currently it looks like this:

in langname.lang.Array:

```<code>class Array<T>
{
  Memory<T> memblock;

  /* Shortened versions of significant functions */

  T & operator[](int index)
  {
    return memblock[index]
  }

  int size()
  {
    return memblock.size()
  }

  void resize(int newSize)
  {
    /* pseudo code */
    newMem = new Memory<T>(newSize)
    for ref in memblock by key
      newMem[key] = ref
    memblock = newMem
  }
}
</code>```

in langname.util.Vector:

```<code>class Vector<T> extends Array<T>
{
  int count; // number of elements actually being used by the vector

  /* Shortened versions of significant functions */

  T & operator[](int index)
  {
    return super.operator[](index);
  }

  int size()
  {
    return count;
  }

  void resize(int newSize)
  {
    /* brief pseudo code */
    if(newSize > super.size())
      super.resize(newSize);

    while(count < newSize)  // in-case the array is expanding
      push() // add new empty elements until count == newSize
      count++;

    while(count > newSize) // in-case the array is shrinking
      pop() // remove elements until count == newSize
      count--;
  }
}
</code>```

The Memory class encapsulates the concept of a block of memory and contains only natively implemented methods. The language has overloadable operators and references so the arr[index] syntax will be used to access elements. I am familiar with the Liskov substitution principle and the Vector type currently behaves exactly like an Array should when used as such. The code showed above is shortened for the sake of brevity.

I figured this was a good idea because Vectors are essentially resizeable arrays and this would allow Vectors to be used whenever a function expects an array. Is this wrong practically or idiomatically and will I run into trouble further down the road?

答:
Invalid Data

One other things glaring out to me in your design is that your Vector class seems to assume, as a result of that count member, that not all of the elements in the array have been meaningfully initialized. So you might have a memory block with 100 elements even though the Vector is only using 75 of them.

Yet Array offers a size method anyway which returns the total size of the memory block.

Now passing that Vector through to a function which accepts an Array reference/pointer and traverses all the elements in the Array can then easily be wasting work if not outright causing a bug, as it might assume that the entire contents of the Array contain meaningfully-initialized values for the elements.

This might not be a problem on its own if Vector overrides the size method (in which case we end up with a dynamic dispatch cost covered below), but if you combine it with the slicing issue described below, then it can become a very real, yet very obscure threat to a complex codebase.

One thing I would suggest at the very least if you use Array this way is to take out that size method. Functions which input an array should be given a size parameter separately, or Arrays should never be used as Vector uses them (they should never be bigger than the number of elements actually meaningfully stored/initialized within them).

Object Slicing

Whenever I see inheritance used like this in C++ at least from one concrete, self-sufficient class to another, it can be a potential smell.

One of the issues you can encounter here is slicing.

You might pass an instance of a Vector to a function which accepts a reference to an Array, e.g., in which the function makes a copy. The function then inadvertently slices away the Vector bits and only produces an Array when its intention was instead to produce a precise replica. Now when interacting with the invalid data issue above, this potentially becomes a very serious problem (even worse than usual slicing scenarios).

A way to protect yourself from this is to always inherit from classes which are at least partially abstract (cannot be instantiated on their own). It's often useful, in C++ at least, to make sure your base classes cannot be instantiated -- only the leaves of your inheritance hierarchy (which are kind of sealed, final subclasses, not to be inherited further) and not the branches and roots, as anything less is always susceptible to object slicing.

That's for C++ though, where things like copy construction do not involve dynamic dispatch. Since you're designing your own language, you might be able to have one where copying a Vector through a base pointer/reference can result in another Vector, thereby eliminating the object slicing problem outright. This would change the existing dynamics of inheritance in a C++-esque language quite a bit. I wouldn't know what to make of such a language, as it would be venturing into unexplored territory. Yet there would be an inherent performance cost to one that did this uniformly, and even if not (ex: having overridable copy constructors), that cost would be required for your above example in order to avoid slicing.

Dynamic Dispatch

By nature, if you allow destruction to occur on a Vector through a reference to an Array, it requires at least dynamic dispatch for destruction (some form of runtime checking through an Array which determines exactly what kind of Array it is and performs branching to execute the appropriate instructions to free the resources). Since Vector and Array have a different size (with Vector introducing a new count field), the instructions to free their memory (both from stack and heap) would have to be different.

Inheritance always implies polymorphism and dynamic dispatch at least in the context of releasing/destroying unless it's impossible to destroy objects through a base pointer.

Of course if you disallow the case of releasing resources through a base pointer/reference, then the dynamic dispatch overhead would go away (unless you avoid the object slicing issues mentioned above, in which case they would come back again for copying). But you probably don't want to do that, since it would make it impossible to create a polymorphic base container, like a list storing references to Array which actually refer to a Vector, let alone a list of references to a Mammal which actually contains a list of Dog and Cat instances.

Efficiency in Context

In the context of a library as general-purpose as a standard library accompanying a language, efficiency takes on a different nature.

It's no longer sufficient to just make it "fast enough" against some real-world user operation. Speed here no longer becomes about making specific operations "fast enough". Speed starts to become a form of generality. The faster your uber-general-purpose library becomes, the more applicable it becomes and fulfills that goal of being generally applicable.

When standard libraries lack speed, it then causes developers to avoid using them in performance-critical scenarios. And that defeats a lot of the purpose of a general library if alternative approaches can easily outperform them.

The reason something like std::vector in C++ is so successful is because when comparing it to alternative methods of creating a growable, dynamically-sized array, people find they can't beat its performance. For apples to apples to comparisons, std::vector gets pretty close to optimal. Now if vector started paying the overhead of dynamic dispatch in functions like operator[], let alone in constructing or destroying it, a lot of that optimal efficiency would be lost.

So a lot of the key to the success of C++'s standard library comes from avoiding dynamic dispatch cost and vtable/vptr costs (vtable costs are usually trivial, but can actually start to get explosive when combined with code generation techniques like templates). A lot of what you are doing above indicates paying such cost somewhere, somehow.

Dynamic Dispatch Part Two

Since there was an expressed interest in this efficiency aspect, the most performance-critical function of something like Vector tends to be operator[] and possibly iterators (if it provides them).

If you allow a Vector to actually be considered an Array rather than containing one, then a function that inputs an Array by reference that receives a Vector then has to pay a dynamic (aka virtual) dispatch overhead like this:

When f in the above diagram calls Array::operator[], it then requires inspecting the type of Array in some form in order to resolve that what it's actually calling here is Vector::operator[]. That's dynamic dispatch, and the biggest overhead there isn't even necessarily branching but because it introduces an unknown to the compiler which can only be resolved at runtime. That then defeats a lot of the optimizer's ability to optimize the hell out of this function call (inlining it, e.g.), as it can't know what function is going to actually be called until the program is executed and the appropriate inputs are provided (that is, unless it's an exceptionally smart optimizer that will generate a different set of instructions when you pass a Vector down the call stack and effectively perform code generation even outside a generic context).

This dynamic dispatch overhead doesn't have to be present if Vector doesn't inherit from Array and the array is marked as final/sealed. In that case, a decent optimizer will make calls to operator[] as cheap as indexing a native array, as with the case with std::vector::operator[] in C++.

Downcasting

Another problem that can occur when inheriting like this is that it might lead to the temptation to occasionally downcast. That temptation can be ever-present in the context of inheritance, but here we don't have to use inheritance (I'll get to that point finally).

The fact that this code suggests merely allowing going from a reference to a Vector to Array and back to Vector again might encourage poor behavior in ways that we can avoid with an iron fist.

When in Doubt, Prefer Composition

Whenever there's a doubt as to whether to use inheritance or composition, favor the latter. It has far fewer ways of being misused. So I suggest something more like this:

class Vector<T>
{
    Array<T> array; // array used for the vector
    int count;      // number of elements actually being used

    T& operator[](int index)
    {
        return array[index];
    }

    int size()
    {
        return count;
    }

    void resize(int newSize)
    {
        /* brief pseudo code */
        if(newSize > array.size())
            array.resize(newSize);

        while(count < newSize)  // in-case the array is expanding
            push() // add new empty elements until count == newSize
            count++;

        while(count > newSize) // in-case the array is shrinking
            pop() // remove elements until count == newSize
            count--;
    }
};
```

<p>... this doesn't have as much syntactical sugar since you might have to explicitly call an accessor function, e.g., to get access to the array contents of a vector in order to pass the contents through to a function which inputs an <code>Array</code> by const reference or by value, e.g. Yet this solution can mitigate if not avoid all the issues described above (invalid data, implicit slicing, dynamic dispatch cost, and the temptation to downcast).</p>

<p>It also avoids the potential for the fragile base class syndrome outright. You're free if you use composition as suggested here, to change the implementation details of <code>Array</code> all you like. As long as you don't invalidate the interface requirements which <code>Vector</code> depends on to work, <code>Vector</code> is guaranteed to continue to work in spite of such changes. We don't get this kind of hard guarantee if <code>Vector</code> inherits from <code>Array</code> and potentially has access to some of its details.</p>

<p>So whenever in doubt, I strongly recommend composition. Inheritance is most naturally used when your classes model a subset of a concept (ex: a <code>Cat</code> is a subset of the concept of <code>Mammal</code>). It's almost always awkward and unnatural when used to model something that seems more like a superset. While the superset/subset distinction might not be so distinctly clear in this context, the fact that it might be a bit fuzzy is another reason to reach for composition.</p>

<p><strong>Alternative Strategy</strong></p>

<p>I don't understand the dynamics of your language very well, but an alternative strategy you could potentially explore is to have something like an "array handle", constructed on the fly. Example using overly simplistic code:</p>

<pre class="lang-cpp prettyprint-override"><code>// Doesn't own memory, just provides a temporary handle to
// existing memory in another data structure.
template <class T>
struct ArrayHandle
{
    // Returns the nth element.
    T& operator[](int n)
    {
        assert(n >= 0 && n < size && "n is out of bounds!");
        return ptr[n];
    }

    // Ideally private members, just using struct here for simplicity.
    T* ptr;
    int size;
};
</code>```

This then gives you a uniform target to decay your data structures to which constructs a handle to contiguous memory on the fly. Both Vector and Array can then provide a method to obtain this handle and pass it along to functions that want to work with a contiguous block of elements.

There's no optimization barrier here, no dynamic dispatch, and it gives you a uniform, homogeneous target type used for parameter passing that lets you uniformly work with contiguous data structures, whether it's coming from Arrays or Vectors or something else.

Against any decent optimizer, invoking operator[] for ArrayHandle there will become as cheap as indexing a native array.

Body:
Invalid Data

One other things glaring out to me in your design is that your Vector class seems to assume, as a result of that count member, that not all of the elements in the array have been meaningfully initialized. So you might have a memory block with 100 elements even though the Vector is only using 75 of them.

Yet Array offers a size method anyway which returns the total size of the memory block.

Now passing that Vector through to a function which accepts an Array reference/pointer and traverses all the elements in the Array can then easily be wasting work if not outright causing a bug, as it might assume that the entire contents of the Array contain meaningfully-initialized values for the elements.

This might not be a problem on its own if Vector overrides the size method (in which case we end up with a dynamic dispatch cost covered below), but if you combine it with the slicing issue described below, then it can become a very real, yet very obscure threat to a complex codebase.

One thing I would suggest at the very least if you use Array this way is to take out that size method. Functions which input an array should be given a size parameter separately, or Arrays should never be used as Vector uses them (they should never be bigger than the number of elements actually meaningfully stored/initialized within them).

Object Slicing

Whenever I see inheritance used like this in C++ at least from one concrete, self-sufficient class to another, it can be a potential smell.

One of the issues you can encounter here is slicing.

You might pass an instance of a Vector to a function which accepts a reference to an Array, e.g., in which the function makes a copy. The function then inadvertently slices away the Vector bits and only produces an Array when its intention was instead to produce a precise replica. Now when interacting with the invalid data issue above, this potentially becomes a very serious problem (even worse than usual slicing scenarios).

A way to protect yourself from this is to always inherit from classes which are at least partially abstract (cannot be instantiated on their own). It's often useful, in C++ at least, to make sure your base classes cannot be instantiated -- only the leaves of your inheritance hierarchy (which are kind of sealed, final subclasses, not to be inherited further) and not the branches and roots, as anything less is always susceptible to object slicing.

That's for C++ though, where things like copy construction do not involve dynamic dispatch. Since you're designing your own language, you might be able to have one where copying a Vector through a base pointer/reference can result in another Vector, thereby eliminating the object slicing problem outright. This would change the existing dynamics of inheritance in a C++-esque language quite a bit. I wouldn't know what to make of such a language, as it would be venturing into unexplored territory. Yet there would be an inherent performance cost to one that did this uniformly, and even if not (ex: having overridable copy constructors), that cost would be required for your above example in order to avoid slicing.

Dynamic Dispatch

By nature, if you allow destruction to occur on a Vector through a reference to an Array, it requires at least dynamic dispatch for destruction (some form of runtime checking through an Array which determines exactly what kind of Array it is and performs branching to execute the appropriate instructions to free the resources). Since Vector and Array have a different size (with Vector introducing a new count field), the instructions to free their memory (both from stack and heap) would have to be different.

Inheritance always implies polymorphism and dynamic dispatch at least in the context of releasing/destroying unless it's impossible to destroy objects through a base pointer.

Of course if you disallow the case of releasing resources through a base pointer/reference, then the dynamic dispatch overhead would go away (unless you avoid the object slicing issues mentioned above, in which case they would come back again for copying). But you probably don't want to do that, since it would make it impossible to create a polymorphic base container, like a list storing references to Array which actually refer to a Vector, let alone a list of references to a Mammal which actually contains a list of Dog and Cat instances.

Efficiency in Context

In the context of a library as general-purpose as a standard library accompanying a language, efficiency takes on a different nature.

It's no longer sufficient to just make it "fast enough" against some real-world user operation. Speed here no longer becomes about making specific operations "fast enough". Speed starts to become a form of generality. The faster your uber-general-purpose library becomes, the more applicable it becomes and fulfills that goal of being generally applicable.

When standard libraries lack speed, it then causes developers to avoid using them in performance-critical scenarios. And that defeats a lot of the purpose of a general library if alternative approaches can easily outperform them.

The reason something like std::vector in C++ is so successful is because when comparing it to alternative methods of creating a growable, dynamically-sized array, people find they can't beat its performance. For apples to apples to comparisons, std::vector gets pretty close to optimal. Now if vector started paying the overhead of dynamic dispatch in functions like operator[], let alone in constructing or destroying it, a lot of that optimal efficiency would be lost.

So a lot of the key to the success of C++'s standard library comes from avoiding dynamic dispatch cost and vtable/vptr costs (vtable costs are usually trivial, but can actually start to get explosive when combined with code generation techniques like templates). A lot of what you are doing above indicates paying such cost somewhere, somehow.

Dynamic Dispatch Part Two

Since there was an expressed interest in this efficiency aspect, the most performance-critical function of something like Vector tends to be operator[] and possibly iterators (if it provides them).

If you allow a Vector to actually be considered an Array rather than containing one, then a function that inputs an Array by reference that receives a Vector then has to pay a dynamic (aka virtual) dispatch overhead like this:

When f in the above diagram calls Array::operator[], it then requires inspecting the type of Array in some form in order to resolve that what it's actually calling here is Vector::operator[]. That's dynamic dispatch, and the biggest overhead there isn't even necessarily branching but because it introduces an unknown to the compiler which can only be resolved at runtime. That then defeats a lot of the optimizer's ability to optimize the hell out of this function call (inlining it, e.g.), as it can't know what function is going to actually be called until the program is executed and the appropriate inputs are provided (that is, unless it's an exceptionally smart optimizer that will generate a different set of instructions when you pass a Vector down the call stack and effectively perform code generation even outside a generic context).

This dynamic dispatch overhead doesn't have to be present if Vector doesn't inherit from Array and the array is marked as final/sealed. In that case, a decent optimizer will make calls to operator[] as cheap as indexing a native array, as with the case with std::vector::operator[] in C++.

Downcasting

Another problem that can occur when inheriting like this is that it might lead to the temptation to occasionally downcast. That temptation can be ever-present in the context of inheritance, but here we don't have to use inheritance (I'll get to that point finally).

The fact that this code suggests merely allowing going from a reference to a Vector to Array and back to Vector again might encourage poor behavior in ways that we can avoid with an iron fist.

When in Doubt, Prefer Composition

Whenever there's a doubt as to whether to use inheritance or composition, favor the latter. It has far fewer ways of being misused. So I suggest something more like this:

class Vector<T>
{
    Array<T> array; // array used for the vector
    int count;      // number of elements actually being used

    T& operator[](int index)
    {
        return array[index];
    }

    int size()
    {
        return count;
    }

    void resize(int newSize)
    {
        /* brief pseudo code */
        if(newSize > array.size())
            array.resize(newSize);

        while(count < newSize)  // in-case the array is expanding
            push() // add new empty elements until count == newSize
            count++;

        while(count > newSize) // in-case the array is shrinking
            pop() // remove elements until count == newSize
            count--;
    }
};

... this doesn't have as much syntactical sugar since you might have to explicitly call an accessor function, e.g., to get access to the array contents of a vector in order to pass the contents through to a function which inputs an Array by const reference or by value, e.g. Yet this solution can mitigate if not avoid all the issues described above (invalid data, implicit slicing, dynamic dispatch cost, and the temptation to downcast).

It also avoids the potential for the fragile base class syndrome outright. You're free if you use composition as suggested here, to change the implementation details of Array all you like. As long as you don't invalidate the interface requirements which Vector depends on to work, Vector is guaranteed to continue to work in spite of such changes. We don't get this kind of hard guarantee if Vector inherits from Array and potentially has access to some of its details.

So whenever in doubt, I strongly recommend composition. Inheritance is most naturally used when your classes model a subset of a concept (ex: a Cat is a subset of the concept of Mammal). It's almost always awkward and unnatural when used to model something that seems more like a superset. While the superset/subset distinction might not be so distinctly clear in this context, the fact that it might be a bit fuzzy is another reason to reach for composition.

Alternative Strategy

I don't understand the dynamics of your language very well, but an alternative strategy you could potentially explore is to have something like an "array handle", constructed on the fly. Example using overly simplistic code:

// Doesn't own memory, just provides a temporary handle to
// existing memory in another data structure.
template <class T>
struct ArrayHandle
{
    // Returns the nth element.
    T& operator[](int n)
    {
        assert(n >= 0 && n < size && "n is out of bounds!");
        return ptr[n];
    }

    // Ideally private members, just using struct here for simplicity.
    T* ptr;
    int size;
};

This then gives you a uniform target to decay your data structures to which constructs a handle to contiguous memory on the fly. Both Vector and Array can then provide a method to obtain this handle and pass it along to functions that want to work with a contiguous block of elements.

There's no optimization barrier here, no dynamic dispatch, and it gives you a uniform, homogeneous target type used for parameter passing that lets you uniformly work with contiguous data structures, whether it's coming from Arrays or Vectors or something else.

Against any decent optimizer, invoking operator[] for ArrayHandle there will become as cheap as indexing a native array.


问:
Is it better to have a single, more general directive or multiple type based directives in Angular?
Is it considered good practice to have:

Single, general directive that has multiple data-* parameters and serial data is binded from controller

Single, general directive that has config and serial data is  from controller

Multiple directives that has some pre-defined config inside directive,   some of config is by data-* parameters and serial data is binded from controller

For example, I have a template were I need to create ~16 charts (Highcharts/amCharts). All of them won't have the same configuration and serial data.

Example of 1 option:

```<code>angular.module('myApp')
  .directive('ngHighcharts', () => ({
    restrict: 'AE',
    replace: 'true',
    scope: {
      data: '='
    },
    template: '<div></div>',
    link: function(scope, $elem, $attrs) {

      var chart, config;
      config = {
        chart: {
          renderTo: $elem[0],
          type: $attrs.type ? $attrs.type : 'bar'
        },
        exporting: {
          enabled: $attrs.exporting ? $attrs.exporting : false
        },
        title: {
          text: $attrs.title ? $attrs.title : ''
        },
        xAxis: {
          categories: $attrs.categories ? $attrs.categories : data[0]
        },
        tooltip: {
          valueSuffix: $attrs.valueSuffix ? $attrs.valueSuffix : ''
        },
        plotOptions: {
          bar: {
            dataLabels: {
              enabled: $attrs.dataLabels ? $attrs.dataLabels : false
            }
          }
        },
        series: scope.data
      };

      chart = new Highcharts.Chart(config);

      scope.$on('$destroy', function () {
        scope.$evalAsync(function () {
          chart.destroy ();
        });
      });

    }
   }));
</code>```

Example of 2 option:

```<code>angular.module('myApp')
  .directive('ngHighcharts', () => ({
    restrict: 'AE',
    replace: 'true',
    scope: {
      config: '=',
      data: '='
    },
    template: '<div></div>',
    link: function(scope, $elem, $attrs) {

      config.chart.renderTo = $elem[0];
      var chart = new Highcharts.Chart(config);

      scope.$on('$destroy', function () {
        scope.$evalAsync(function () {
          chart.destroy ();
        });
      });

    }
   }));
</code>```

Example of 3 option:

```<code>angular.module('myApp')
  .directive('ngHighcharts', () => ({
    restrict: 'AE',
    replace: 'true',
    scope: {
      data: '='
    },
    template: '<div></div>',
    link: function(scope, $elem, $attrs) {

      var chart, config;
      config = {
        chart: {
          renderTo: $elem[0],
          type: 'bar'
        },
        exporting: {
          enabled: true
        },
        title: {
          text: $attrs.title ? $attrs.title : ''
        },
        xAxis: {
          categories: $attrs.categories ? $attrs.categories : data[0]
        },
        tooltip: {
          valueSuffix: $attrs.valueSuffix ? $attrs.valueSuffix : ''
        },
        plotOptions: {
          bar: {
            dataLabels: {
              enabled: true
            }
          }
        },
        series: scope.data
      };

      chart = new Highcharts.Chart(config);

      scope.$on('$destroy', function () {
        scope.$evalAsync(function () {
          chart.destroy ();
        });
      });

    }
   }));
</code>```

What would be considered best practice in this situation?

答:
It really depends on the use case. You describe a chart directive. At first glance, its configuration appears fairly static. That is, you can configure it per view and not give it a second thought. In that case, attribute-based configuration is nice. Coupled with some sensible defaults, it greatly reduces the moving parts from outside your directive.

The thing is, life is rarely that simple (or fair). Imagine that your boss shows up an hour before end-of-work on Friday. She's just come from a meeting of project shareholders and was blindsided by their assumption that salespeople could configure reports (including charts) as they saw fit. This makes your attribute-based configuration not only wrong, but less straightforward to "fix". (I won't call it a true fix since it's a new requirement.) If configuration had always been data, it would be conceptually simple to change the data source. (Never mind there are new UIs to build and now you're going to miss Happy Hour at The Stumble Inn.)

So, it's a tradeoff like everything else. It's flexibility versus simplicity. Flexibility is always cool, but its cost is complexity. You have to decide what you value. You can't get something for free. Remember TANSTAAFL.

ContentLicense: CC BY-SA 3.0


问:
If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?
In many books and tutorials, I've heard the practice of memory management stressed and felt that some mysterious and terrible things would happen if I didn't free memory after I'm done using it.

I can't speak for other systems (although to me it's reasonable to assume that they adopt a similar practice), but at least on Windows, the Kernel is basically guaranteed to cleanup most resources (with the exception of an odd few) used by a program after program termination. Which includes heap memory, among various other things.

I understand why you would want to close a file after you're done using it in order to make it available to the user or why you would want to disconnect a socket connected to a server in order to save bandwidth, but it seems silly to have to micromanage ALL your memory used by your program.

Now, I agree that this question is broad since how you should handle your memory is based on how much memory you need and when you need it, so I will narrow the scope of this question to this: If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?

Edit:
The question suggested as a duplicate was specific to the Unix family of operating systems. Its top answer even specified a tool specific to Linux (e.g. Valgrind). This question is meant to cover most "normal" non-embedded operating systems and why it is or isn't a good practice to free memory that is needed throughout the lifespan of a program.

答:
If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?

It is not mandatory, but it can have benefits (as well as some drawbacks).

If the program allocates memory once during its execution time, and would otherwise never release it until the process ends, it may be a sensible approach not to release the memory manually and rely on the OS. On every modern OS I know, this is safe, at the end of the process all allocated memory is reliably returned to the system.

In some cases, not cleaning up the allocated memory explicitly may even be notably quicker than doing the clean-up.

However, by releasing all the memory at end of execution explicitly,

during debugging / testing, mem leak detection tools won't show you "false positives"

it might be much easier to move the code which uses the memory together with allocation and deallocation into a separate component and use it later in a different context where the usage time for the memory need to be controlled by the user of the component

The lifespan of programs can change. Maybe your program is a small command line utility today, with a typical lifetime of less than 10 minutes, and it allocates memory in portions of some kb every 10 seconds - so no need to free  any allocated memory at all before the program ends. Later on the program is changed and gets an extended usage as part of a server process with a lifetime of several weeks - so not freeing unused memory in between is not an option any more, otherwise your program starts eating up all available server memory over time. This means you will have to review the whole program and add deallocating code afterwards. If you are lucky, this is an easy task, if not, it may be so hard that chances are high you miss a place. And when you are in that situation, you will wish you had added the "free" code to your program beforehand, at the time when you added the "malloc" code.

More generally, writing allocating and related deallocating code always pairwise counts as a "good habit" among many programmers: by doing this always, you decrease the probability of forgetting the deallocation code in situations where the memory must be freed.


问:
JSON API specification : When do I need to return a 404 not found?
I'm working on a REST api following the JSON api specification and I'm struggling with the "no data" responses (described here).

A server MUST respond with 404 Not Found when processing a request to
  fetch a single resource that does not exist, except when the request
  warrants a 200 OK response with null as the primary data (as described
  above).

The "described above" refers to the previous section of the specification :

A server MUST respond to a successful request to fetch an individual
  resource with a resource object or null provided as the response
  document's primary data.

null is only an appropriate response when the requested URL is one
  that might correspond to a single resource, but doesn't currently.

I don't understand when I need to return a HTTP 404 Not Found and when I need with HTTP 200 OK with {"data":null}.

For example, if I have the following URL :

```<code>http://example.org/users/52
</code>```

This URL is correct, but the User referenced by the ID 52 doesn't exist.What is the correct response ? A 404 or a 200 data: null ?

答:
If the user 52 doesn't exist, return HTTP 404. Returning HTTP 200 is misleading.

Think about it from the point of view of the client. Would the following dialog make sense to you?

Client: please, I want to know something about user 52.

  Server: of course (HTTP 200). What do you want to know?

  Client: I want to know the basic information about the user.

  Server: There is no information whatsoever about this user; I don't even know what are you talking about.

The case where you could use HTTP 200 with null is when you don't have information about a part of the entry being requested. Imagine a case where the users have a purchase history, unless they registered very recently and haven't been approved yet (and cannot order anything). For an ordinary, approved user, the response will be:

HTTP/1.1 200 OK

{
    "id": 51,
    "name": "Laura Norman",
    "purchase-history": [
        { ... },
        ...
    ]
}
```

<p>Instead, the user 52 doesn't have a purchase history:</p>

<pre class="lang-js prettyprint-override"><code>HTTP/1.1 200 OK

{
    "id": 52,
    "name": "David Johnson",
    "purchase-history": null
}
</code>```

This is semantically different from an empty sequence. "purchase-history": [] means that the user has a history, but haven't purchased anything yet. A null has a very different meaning.

Body:
If the user 52 doesn't exist, return HTTP 404. Returning HTTP 200 is misleading.

Think about it from the point of view of the client. Would the following dialog make sense to you?

Client: please, I want to know something about user 52.

  Server: of course (HTTP 200). What do you want to know?

  Client: I want to know the basic information about the user.

  Server: There is no information whatsoever about this user; I don't even know what are you talking about.

The case where you could use HTTP 200 with null is when you don't have information about a part of the entry being requested. Imagine a case where the users have a purchase history, unless they registered very recently and haven't been approved yet (and cannot order anything). For an ordinary, approved user, the response will be:

HTTP/1.1 200 OK

{
    "id": 51,
    "name": "Laura Norman",
    "purchase-history": [
        { ... },
        ...
    ]
}

Instead, the user 52 doesn't have a purchase history:

HTTP/1.1 200 OK

{
    "id": 52,
    "name": "David Johnson",
    "purchase-history": null
}

This is semantically different from an empty sequence. "purchase-history": [] means that the user has a history, but haven't purchased anything yet. A null has a very different meaning.


答:
You could use a language with garbage collection (such as Scheme, Ocaml, Haskell, Common Lisp, and even Java, Scala, Clojure).

(In most GC-ed languages, there is no way to explicitly and manually free memory! Sometimes, some values might be finalized, e.g. the GC and the runtime system would close a file handle value when that value is unreachable; but this is not sure, unreliable, and you should instead close explicitly your file handles, since finalization is never guaranteed)

You could also, for your program coded in C (or even C++) use Boehm's conservative garbage collector. You would then replace all your malloc with GC_malloc  and not bother about free-ing any pointer. Of course you need to understand the pros and conses of using Boehm's GC. Read also the GC handbook.

Memory management is a global property of a program. In some way it (and the liveness of some given data) is non-compositional and non-modular, since a whole program property.

At last, as others pointed out, explicitly free-ing your heap allocated C memory zone is good practice. For a toy program not allocating a lot of memory, you could even decide to not free memory at all (since when the process has ended, its resources, including its virtual address space, would be freed by the operating system).

If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?

No, you don't need to do that. And many real world programs don't bother freeing some memory which is needed on the entire lifespan (in particular the GCC compiler is not freeing some of its memory). However, when you do that (e.g. you don't bother free-ing some particular piece of C dynamically allocated data), you'll better comment that fact to ease the work of future programmers on the same project. I tend to recommend that the amount of unfreed memory stays bounded, and usually relatively small w.r.t. to total used heap memory.

Notice that the system free often does not release memory to the OS (e.g. by calling munmap(2) on POSIX systems) but usually mark a memory zone as reusable by future malloc. In particular, the virtual address space (e.g. as seen thru /proc/self/maps on Linux, see proc(5)....) might not shrink after free (hence utilities like ps or top are reporting the same amount of used memory for your process).

Body:
In many books and tutorials, I've heard the practice of memory management stressed and felt that some mysterious and terrible things would happen if I didn't free memory after I'm done using it.

I can't speak for other systems (although to me it's reasonable to assume that they adopt a similar practice), but at least on Windows, the Kernel is basically guaranteed to cleanup most resources (with the exception of an odd few) used by a program after program termination. Which includes heap memory, among various other things.

I understand why you would want to close a file after you're done using it in order to make it available to the user or why you would want to disconnect a socket connected to a server in order to save bandwidth, but it seems silly to have to micromanage ALL your memory used by your program.

Now, I agree that this question is broad since how you should handle your memory is based on how much memory you need and when you need it, so I will narrow the scope of this question to this: If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?

Edit:
The question suggested as a duplicate was specific to the Unix family of operating systems. Its top answer even specified a tool specific to Linux (e.g. Valgrind). This question is meant to cover most "normal" non-embedded operating systems and why it is or isn't a good practice to free memory that is needed throughout the lifespan of a program.


问:
Fork Management of Git Multi-level Hierarchies
We have the following Git hierarchy structure in place, where each child is forked from the parent. If we build something in Client1 that will be useful in the entire hierarchy, what is the best way to push the changes up to the parents (whether just one level up or all the way to the root), given that we don't wish to push all the Client-specific customizations up the chain.

Now, while the ideal solution might be to do the development at the highest required level, the modules can only really be tested down the chain where all the customizations are instantiated.

E.g. If we develop a Module-New in Client1 repo, and need to push it to Core, what would the best way for that to be done given that we don't want Client1's customizations in the core? On the other hand, if we had originally developed ModuleA directly in CORE, we would have had to push the changes downstream all the way to Client1 to test Module-New (and iterate for every change).

Are there any Git Workflows or any other tools that can help establish these rules. We currently use GitFlows to manage our master, develop and feature branches for all repos. Also, is there a way to disable direct pushes into a remote repository?

```<code>                            CORE
                              |
                ------------------------
            Product 1               Product 2
                |                       |
            ----------              ----------
        Client1     Client2     Client3     Client4
           |-v1.0
           |-v1.1
           ...
</code>```

答:
You can disable direct push in repositories depending on which technologies you're using. Preventing push can be done somewhat using git hooks, but if you're using gitlab/github/bitbucket... there should be a way to protect branches.

If all branches are protected and that the dev can't create new branch, then there is no way to push to the repo. This way, you'll have to handle the dev using "merge requests/push requests" or how it's called.

It's unclear what you're actually managing so the following might not help. In my case, we have a core product that is installed on every client, the core product might be installed with different versions. And additional modules can be installed on the side. Either way, usually client customization are usually done by installing specific modules for clients that extend existing modules (including core modules). In my case, customizations for clients never or rarely bubble up to the core product. If we needed to, we could simply move the module into the core product.

If a custom module is shared across multiple clients, we might use special branches that are merged on the master of each module repository.

In the end, it can get quite complicated if code doesn't bubble up to the master branch of each module's repo. In our case, most of the work is achieved using buildout to manage repos and merges and dependencies.

My opinion

Handling dependencies using git repositories should be limited to development even if it looks simpler to just fetch the repos. Git repository can get quite big and sometimes fetching might fail if the repository is big and the internet connection is unstable...Git doesn't allow partial fetch so if it fails at 99%, you'll have to restart from 0% anyway.

For deployment, I think it makes more sense to have package managers do it. They exists and they usually do their jobs well. The advantage of using a package manager is that you don't have to download the whole history of changes that might come with the module. Usually package managers allow partial download using http so you can pause an update later if internet fails. With a good package manager, you could also host your own private package servers for each client. Any module that is similar for each client can be pushed on a central server and every customized package could be pushed to a package server per client.

All of this is fine if you have a way to automate the building process of package and deployment of package on their respective servers.

This way if a client does something like "package update", it could check on the client server for a package and then on the central server and take the right version from this. Old package don't have to be deleted and the client could downgrade its setup as he wish.

My guess, is that it's the nicest thing someone could implement, yet there is no standard way to do that as far as I know. I heard people doing that with python eggs, other with debian packages an so on. But each implementation has their own problems... Like debian packages won't work on windows and non debian distros... pythong eggs are quite limited to python.. npm packages to javascript and so on. If we had a universal package manager that would be simply a piece of cake to implement.


答:
Ignoring languages where you don't free memory manually anyway...

What you think of as "a program" right now might at some point become just a function or method that is part of a larger program. And then that function might get called multiple times. And then memory that you should have "freed manually" will be a memory leak. That is of course a judgment call.

Title: If I need to use a piece of memory throughout the lifespan of my program, is it really necessary to free it right before program termination?


问:
Doesn't "always initialize variables" lead to important bugs being hidden?
The C++ Core Guidelines have the rule ES.20: Always initialize an object.

Avoid used-before-set errors and their associated undefined behavior. Avoid problems with comprehension of complex initialization. Simplify refactoring.

But this rule doesn't help to find bugs, it only hides them.

Let's suppose that a program has an execution path where it uses an uninitialized variable. It is a bug. Undefined behavior aside, it also means that something went wrong, and the program probably doesn't meet its product requirements. When it will be deployed to production, there can be a money loss, or even worse.

How do we screen bugs? We write tests. But tests don't cover 100% of execution paths, and tests never cover 100% of program inputs. More than that, even a test covers a faulty execution path - it still can pass. It's undefined behavior after all, an uninitialized variable can have a somewhat valid value.

But in addition to our tests, we have the compilers which can write something like 0xCDCDCDCD to uninitialized variables. This slightly improves detection rate of the tests.

Even better - there are tools like Address Sanitizer, which will catch all the reads of uninitialized memory bytes.

And finally there are static analyzers, which can look at the program and tell that there is a read-before-set on that execution path.

So we have many powerful tools, but if we initialize the variable - sanitizers find nothing.

```<code>int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.

// Another bug: use empty buffer after read error.
use(buffer);
</code>```

There is another rule - if program execution encounters a bug, program should die as soon as possible. No need to keep it alive, just crash, write a crashdump, give it to the engineers for investigation.

Initializing variables unnecessarily does the opposite - program is being kept alive, when it would already get a segmentation fault otherwise.

答:
A decent C, C++ or Objective-C compiler with the right compiler options set will tell you at compile time if a variable is used before its value is set. Since in these languages using the value of an uninitialised variable is undefined behavior, "set a value before you use" is not a hint, or a guideline, or good practice, it is a 100% requirement; otherwise your program is absolutely broken. In other languages, like Java and Swift, the compiler will never allow you to use a variable before it is initialised.

There is a logical difference between "initialise" and "set a value". If I want to find the conversion rate between dollars and euros, and write "double rate = 0.0;" then the variable has a value set, but it isn't initialised. The 0.0 stored here has nothing whatsoever to do with the correct result. In this situation, if because of a bug you never store the correct conversion rate, the compiler doesn't have a chance to tell you. If you just wrote "double rate;" and never stored a meaningful conversion rate, the compiler would tell you.

So: Don't initialise a variable just because the compiler tells you it is used without being initialised. That is hiding a bug. The real problem is that you are using a variable that you shouldn't be using, or that on one code path you didn't set a value. Fix the problem, don't hide it.

Don't initialise a variable just because the compiler might tell you it is used without being initialised. Again, you are hiding problems.

Declare variables close to use. This improves the chances that you can initialise it with a meaningful value at the point of declaration.

Avoid reusing variables. When you reuse a variable, it is most likely initialised to a useless value when you use it for the second purpose.

It has been commented that some compilers have false negatives, and that checking for initialisation is equivalent to the halting problem. Both are in practice irrelevant. If a compiler, as quoted, cannot find the use of an uninitialized variable ten years after the bug is reported, then it is time to look for an alternative compiler. Java implements this twice; once in the compiler, once in the verifier, without any problems. The easy way to get around the halting problem is not to require that a variable is initialised before used, but that it is initialised before use in a way that can be checked by a simple and fast algorithm.


答:
TL;DR: There are two ways to making this program correct, initializing your variables and praying. Only one delivers results consistently.

Before I can answer your question, I will need to first explain what Undefined Behavior means. Actually, I'll let a compiler author do the bulk of the work:

What Every C Programmer Should Know About Undefined Behavior #1/3

What Every C Programmer Should Know About Undefined Behavior #2/3

What Every C Programmer Should Know About Undefined Behavior #3/3

If you are unwilling to read those articles, a TL;DR is:

Undefined Behavior is a social contract between the developer and the compiler; the compiler assumes with blind faith that its user will never, ever, rely on Undefined Behavior.

The archetype of "Demons flying from your nose" has utterly failed to convey the implications of this fact, unfortunately. While meant to prove that anything could happen, it was so utterly unbelievable that it was mostly shrugged off.

The truth, however, is that Undefined Behavior affects the compilation itself, long before you even attempt to use the program (instrumented or not, within a debugger or not) and can utterly change its behavior.

I find the example in part 2 above striking:

```<code>void contains_null_check(int *P) {
  int dead = *P;
  if (P == 0)
    return;
  *P = 4;
}
</code>```

is transformed into:

```<code>void contains_null_check(int *P) {
  *P = 4;
}
</code>```

because it's obvious that P cannot be 0 since it's dereferenced before being checked.

How does this apply to your example?

```<code>int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.
</code>```

Well, you have made the common mistake of assuming that Undefined Behavior would cause a run-time error. It may not.

Let us imagine that the definition of my_read is:

```<code>err_t my_read(buffer_t buffer, int* bytes_read) {
    err_t result = {};
    int blocks_read = 0;
    if (!(result = low_level_read(buffer, &blocks_read))) { return result; }
    *bytes_read = blocks_read * BLOCK_SIZE;
    return result;
}
</code>```

and proceed as expected of a good compiler with inlining:

```<code>int bytes_read; // UNINITIALIZED

// start inlining my_read

err_t result = {};
int blocks_read = 0;
if (!(result = low_level_read(buffer, &blocks_read))) {
    // nothing
} else {
    bytes_read = blocks_reads * BLOCK_SIZE;
}

// end of inlining my_read

buffer.shrink(bytes_read);
</code>```

Then, as expected of a good compiler, we optimize out useless branches:

No variable should be used uninitialized

bytes_read would be used uninitialized if result was not 0

The developer is promising that result will never be 0!

So result is never 0:

```<code>int bytes_read; // UNINITIALIZED
err_t result = {};
int blocks_read = 0;
result = low_level_read(buffer, &blocks_read);

bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);
</code>```

Oh, result is never used:

```<code>int bytes_read; // UNINITIALIZED
int blocks_read = 0;
low_level_read(buffer, &blocks_read);

bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);
</code>```

Oh, we can postpone the declaration of bytes_read:

```<code>int blocks_read = 0;
low_level_read(buffer, &blocks_read);

int bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);
</code>```

And here we are, a strictly confirming transformation of the original, and no debugger will trap an uninitialized variable because there is none.

I've been down that road, understanding the issue when expected behavior and assembly do not match is really no fun.

Title: Doesn't "always initialize variables" lead to important bugs being hidden?

Body:
The C++ Core Guidelines have the rule ES.20: Always initialize an object.

Avoid used-before-set errors and their associated undefined behavior. Avoid problems with comprehension of complex initialization. Simplify refactoring.

But this rule doesn't help to find bugs, it only hides them.

Let's suppose that a program has an execution path where it uses an uninitialized variable. It is a bug. Undefined behavior aside, it also means that something went wrong, and the program probably doesn't meet its product requirements. When it will be deployed to production, there can be a money loss, or even worse.

How do we screen bugs? We write tests. But tests don't cover 100% of execution paths, and tests never cover 100% of program inputs. More than that, even a test covers a faulty execution path - it still can pass. It's undefined behavior after all, an uninitialized variable can have a somewhat valid value.

But in addition to our tests, we have the compilers which can write something like 0xCDCDCDCD to uninitialized variables. This slightly improves detection rate of the tests.

Even better - there are tools like Address Sanitizer, which will catch all the reads of uninitialized memory bytes.

And finally there are static analyzers, which can look at the program and tell that there is a read-before-set on that execution path.

So we have many powerful tools, but if we initialize the variable - sanitizers find nothing.

```<code>int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.

// Another bug: use empty buffer after read error.
use(buffer);
</code>```

There is another rule - if program execution encounters a bug, program should die as soon as possible. No need to keep it alive, just crash, write a crashdump, give it to the engineers for investigation.

Initializing variables unnecessarily does the opposite - program is being kept alive, when it would already get a segmentation fault otherwise.

Body:
TL;DR: There are two ways to making this program correct, initializing your variables and praying. Only one delivers results consistently.

Before I can answer your question, I will need to first explain what Undefined Behavior means. Actually, I'll let a compiler author do the bulk of the work:

What Every C Programmer Should Know About Undefined Behavior #1/3

What Every C Programmer Should Know About Undefined Behavior #2/3

What Every C Programmer Should Know About Undefined Behavior #3/3

If you are unwilling to read those articles, a TL;DR is:

Undefined Behavior is a social contract between the developer and the compiler; the compiler assumes with blind faith that its user will never, ever, rely on Undefined Behavior.

The archetype of "Demons flying from your nose" has utterly failed to convey the implications of this fact, unfortunately. While meant to prove that anything could happen, it was so utterly unbelievable that it was mostly shrugged off.

The truth, however, is that Undefined Behavior affects the compilation itself, long before you even attempt to use the program (instrumented or not, within a debugger or not) and can utterly change its behavior.

I find the example in part 2 above striking:

void contains_null_check(int *P) {
  int dead = *P;
  if (P == 0)
    return;
  *P = 4;
}

is transformed into:

void contains_null_check(int *P) {
  *P = 4;
}

because it's obvious that P cannot be 0 since it's dereferenced before being checked.

How does this apply to your example?

int bytes_read = 0;
my_read(buffer, &bytes_read); // err_t my_read(buffer_t, int*);
// bytes_read is not changed on read error.
// It's a bug of "my_read", but detection is suppressed by initialization.
buffer.shrink(bytes_read); // Uninitialized bytes_read could be detected here.

Well, you have made the common mistake of assuming that Undefined Behavior would cause a run-time error. It may not.

Let us imagine that the definition of my_read is:

err_t my_read(buffer_t buffer, int* bytes_read) {
    err_t result = {};
    int blocks_read = 0;
    if (!(result = low_level_read(buffer, &blocks_read))) { return result; }
    *bytes_read = blocks_read * BLOCK_SIZE;
    return result;
}

and proceed as expected of a good compiler with inlining:

int bytes_read; // UNINITIALIZED

// start inlining my_read

err_t result = {};
int blocks_read = 0;
if (!(result = low_level_read(buffer, &blocks_read))) {
    // nothing
} else {
    bytes_read = blocks_reads * BLOCK_SIZE;
}

// end of inlining my_read

buffer.shrink(bytes_read);

Then, as expected of a good compiler, we optimize out useless branches:

No variable should be used uninitialized

bytes_read would be used uninitialized if result was not 0

The developer is promising that result will never be 0!

So result is never 0:

int bytes_read; // UNINITIALIZED
err_t result = {};
int blocks_read = 0;
result = low_level_read(buffer, &blocks_read);

bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);

Oh, result is never used:

int bytes_read; // UNINITIALIZED
int blocks_read = 0;
low_level_read(buffer, &blocks_read);

bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);

Oh, we can postpone the declaration of bytes_read:

int blocks_read = 0;
low_level_read(buffer, &blocks_read);

int bytes_read = blocks_reads * BLOCK_SIZE;
buffer.shrink(bytes_read);

And here we are, a strictly confirming transformation of the original, and no debugger will trap an uninitialized variable because there is none.

I've been down that road, understanding the issue when expected behavior and assembly do not match is really no fun.


答:
While Ike's answer is very good, I think it's missing one simple and crucial point:

Public inheritance is an "is a" relationship. E.g. "Audi A8 is a Car"

Vector inheriting from Array means "Vector is an Array". To me it's intuitive that that's not the case. Instead, both are clearly different sequential indexed containers, like a linked list, a deque, a ring buffer, and a few others.

.NET represents this with shared interfaces such as IEnumerable, while C++ uses iterators and template mechanics for the same concept.

Title: Should the Vector type inherit from the Array type in an environment where both are first-class objects

Body:
I have created a programming language that is based on java for a personal project. The language already has generic classes and functions and the generics are completely compatible with primitive types (which I decided not to turn into objects, autoboxed or otherwise).

I am currently designing the Standard Library and having never created a Standard Library I am not sure if making the Vector type inherit from Array would be a disaster or not. Currently it looks like this:

in langname.lang.Array:

```<code>class Array<T>
{
  Memory<T> memblock;

  /* Shortened versions of significant functions */

  T & operator[](int index)
  {
    return memblock[index]
  }

  int size()
  {
    return memblock.size()
  }

  void resize(int newSize)
  {
    /* pseudo code */
    newMem = new Memory<T>(newSize)
    for ref in memblock by key
      newMem[key] = ref
    memblock = newMem
  }
}
</code>```

in langname.util.Vector:

```<code>class Vector<T> extends Array<T>
{
  int count; // number of elements actually being used by the vector

  /* Shortened versions of significant functions */

  T & operator[](int index)
  {
    return super.operator[](index);
  }

  int size()
  {
    return count;
  }

  void resize(int newSize)
  {
    /* brief pseudo code */
    if(newSize > super.size())
      super.resize(newSize);

    while(count < newSize)  // in-case the array is expanding
      push() // add new empty elements until count == newSize
      count++;

    while(count > newSize) // in-case the array is shrinking
      pop() // remove elements until count == newSize
      count--;
  }
}
</code>```

The Memory class encapsulates the concept of a block of memory and contains only natively implemented methods. The language has overloadable operators and references so the arr[index] syntax will be used to access elements. I am familiar with the Liskov substitution principle and the Vector type currently behaves exactly like an Array should when used as such. The code showed above is shortened for the sake of brevity.

I figured this was a good idea because Vectors are essentially resizeable arrays and this would allow Vectors to be used whenever a function expects an array. Is this wrong practically or idiomatically and will I run into trouble further down the road?


答:
Freeing memory at the end of a programs run is just a waste of CPU time. It's like tidying a house before nuking it from orbit.

However sometimes what was a short running program can turn into part of a much longer running one. Then freeing stuff becomes necessary. If this wasn't thought about to at least some extent then it can involve substantial reworking.

One clever solution to this is "talloc" which lets you make a load of memory allocations and then throw them all away with one call.


问:
How to license (PowerShell) GUI Projects
After almost 2 years learning how to code (in Powershell) and some help at Stackoverflow from time to time, I'm now finally on my way to release my first GUI project.

I intend to release the compiled .exe of my project plus the .ps1 files at github or similar with the hopes that other experts can help me with tips how to optimise the code so that I can learn even some pro tips :-)

However I need a little help licensing it. For now I plan to release it under GPLv3.
How exactly should I do this? From what I have read so far, I would do it like this:

Put the license text at top of my source code

also add an extra .txt file with the same license text into the archive with the GUI.exe

Is this correct? Are there any more steps required?

Also: Is there a way to exclude commercial use?
And what should I do with functions other people posted on blogs? Should I name them as a contributer in the license file or is it enough to leave all the infos in the function header?

The current license text I plan to use

```<code>Programname and short description.

Copyright (C) 2015  [ME]

This is a free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.

Contributed by [me] <myEmail>
</code>```

答:
The abbreviated GPL text above says "You should have received a copy of the GNU General Public License along with [product]". This often refers to a file LICENSE which includes the full text of the GPL.

When you have lots of contributors you would like to credit, common practice is to include an AUTHORS or CONTRIBUTORS file where you list them all.

I don't know how complex your GUI application is. When it is more complex, it might be appropriate to add an "About" dialog which shows the license and lists the contributors.

Regarding non-commercial licensing: In that case the GPL is out of the question. One of the central dogmas of open source / free software, is that software should be free to use for any purpose, including commercial use. Forbidding commercial use is often difficult, because it's very hard to define what is and what is not commercial use. For example, Github is a commercial company. They make money (indirectly) by hosting your files. Isn't that commercial use, too?


问:
Methods of separating front and back-end with full stack javascript?
Suppose I have a front-end which is mostly a single-page application written using angular, grunt, and bower.  And suppose I have a backend, which is mostly just a REST API sitting on top of an ORM, which stores/retrieves objects from a database, using things like grunt, express and sequelize.

The angular application does all of the visual stuff the user sees, but it does so by being a GUI over the services provided by the back-end.

It would be desirable to separate these into two different codebases, to permit independent development, versioning, continuous integration, push to development, etc.

My question is, what methods are out there for doing this cleanly?  Are there recommended best practices for full-stack javascript?

Option #1 seems to be a monolith, i.e. "don't separate them".  The pro is that the build chain is simple, and everything is in one place - but there seem to be many cons; harder to version independently, a broken front means an un-deployable back, and so on.

Option #2 seems to be a quasi-monolith, where the front-end build chain results in writing a bunch of files to the back-end.  The dist directory on the front-end would refer to some directory on the back-end, so essentially when the front end minifies, uglifies, etc, it ends up publishing to the back-end, which runs everything.

Option #3 seems full-separation: front-end and back-end each run their own servers on different ports, and they are fully separate projects.  The drawback seems that they need to be configured to know about each other's ports; the back-end must allow CORS from the front-end, and the front-end needs to know where all those endpoints are expected to be.

Option #4 might be to use something like docker-compose to rig the whole thing together.

I'm sure there are other options.  What's the recommended best practice?

答:
Yes, you should separate the two and treat the front end app like a 3rd party app--you may eventually add another client, a mobile app for example, and if the first client has been built this way your life will be easier.

Using docker containers or another deployment system mostly pertains to the backend, as the front end of your app are just static assets that need to be resolved. You can either host those assets statically in your server or somewhere else like a CDN like cloudfront.

Avoiding cors will save you a Little configuration, but as the above answer mentioned, that's sortof the point. Using cors (and token auth) will better prepare your backend for other clients as well.

Edit: as far as full stack js best practices--I would just say this, be consistent. If you're using promises (and you should), do it on both sides. Keep the same js style and formatting, use the same testing libs (where possible), etc.


答:
It is not necessary, as in you will not fail to execute your program properly if you fail to.  However, there are reasons you may choose to, if given a chance.

One of the most powerful cases I run into (over and over) is that someone writes a small piece of simulation code that runs in their executable.  They say "we'd like this code to be integrated into the simulation."  I then ask them how they plan to re-initialize between monte-carlo runs, and they look at me blankly.  "What do you mean re-initialize?  You just run the program with new settings?"

Sometimes a clean cleanup makes it much easier for your software to be used.  In the case of many examples, you presume you never need to clean something up, and you make assumptions about how you can handle the data and its lifespan around those presumptions.  When you move to a new environment where those presumptions are not valid, entire algorithms may no longer work.

For an example of just how strange things can get, look at how the managed languages deal with finalization at the end of processes, or how C# deals with the programmatic halting of Application Domains.  They tie themselves in knots because there's assumptions that fall through the cracks in these extreme cases.


问:
Python's join seems to focus not on the items to join, but on the symbol, as compared to Ruby or Smalltalk, for a design reason?
I thought one of the cornerstone of OOP is that, we have objects, which are the items we are interested in dealing with, and then we send messages to them.

So it may seem natural that, I have a collection of items, and I need to put them into one string, so to do it:

```<code>  ["x", "o", "o"].join(" | ")    # joining a tic-tac-toe row in Ruby
</code>```

(Smalltalk does it the same way).  The " | " is in some way thought of as an argument, one token of how to join it.  It can be " " too, if the game board is to be simpler.  So the joining element " | " is not particularly something we have interest in -- it is not the main objects in the program that have particular importance or significance.

If Python does it using

```<code>  " | ".join(["x", "o", "o"])
</code>```

It does feel somewhat strange that it almost feels like we are passing a message to the argument, to tell the argument about something.  Maybe Python is more procedural?  To tell the joining string to perform some duty for us?

Is it to save implementation, so that we don't have to define a join for each collection class we have?  But isn't it true that we can also just write once for any collection class, such as in Ruby:

```<code>module Enumerable
  def my_join(joiner)
    self.inject {|a,b| a.to_s + joiner + b.to_s}
  end
end
</code>```

(something like this, calling to_s on each item, relying on the to_s of each class to do its own proper thing, to convert to a string, and then concatenating them). So then we don't have to implement for each of String, Hash, or Set, or whatever collection class we have.

Or does Python out right doesn't go the OOP route?  It uses len("abc") and type([]) instead of "abc".len() or [].type() even in Python3 too it seems.  Does Python do it this way for a design reason?

答:
Python's join is designed to work on any iterable. This means the designers had to decide where to put it. Since it works on more than just lists, but always requires(separator) and returns a string, they decided to make it part of the string type.

Armin Ronacher says it better than me:

http://lucumr.pocoo.org/2011/7/9/python-and-pola/#seemingly-inverse-logic

"Imagine Python would not work that way. You would have to convert the
  iterable into an actual list first to convert it into a string. Ruby
  people will now argue that Ruby solves this problem with mixing in
  modules, and they are certainly correct that this is an option. But
  this is a concious design decision in the language which has many
  implications. Python encourages loose coupling by having these
  protocols where the actual implementations can be elsewhere. One
  object is iterable, another part in the system knows how to make it
  into a string."


问:
Signature-changing decorator: properly documenting additional argument
Let's say I have a custom decorator, and I want it to properly handle docstring of decorated function. Problem is: my decorator adds an argument.

```<code>from functools import wraps

def custom_decorator(f):
    @wraps(f)
    def wrapper(arg, need_to_do_more):
        '''
        :param need_to_do_more: if True: do more
        '''
        args = do_something(arg)

        if need_to_do_more:
            args = do_more(args)

        return f(args)

    return wrapper
</code>```

You can see the argument is not actually passed to decorated function, but used by the wrapper - which may or may
not be relevant here.

How can I properly handle documenting the additional argument?
Is it a good practice for a wrapper to take an additional argument, or should I avoid it?

Or should I rather use a different solution, like:

making wrapper a simple higher order function, with the function it calls passed as the third argument

refactoring the wrapper into two separate functions?

答:
Changing method signature using decorator is something that in most cases violates Principle Of Least Astonishment:

The Principle of Least Astonishment states that the result of performing some operation should be obvious, consistent, and predictable, based upon the name of the operation and other clues.

The exceptions I could come up are:

decorator in its name clearly states that method signature is changed. Example of such decorator is @property.

decorated method is not intended to be invoked directly by client code

decorator is used for some kind of adaptation (like Adapter pattern)

Nevertheless, usually decorators are usually implemented for decorating functions (like in Decorator pattern, although authors of the decorator feature opposed this similarities), which implies that method signature (including list of parameters) is not changed.

As an alternative to implicitly adding new parameter I propose to make this explicit - any decorated function must declare such parameter on the list of parameters. You can check function parameter names using method described in this SO answer and throw exception if decorated function does not have such parameter.

Implicit parameter or requiring parameter should be described in decorator docstring (custom_decorator in your example). If you use @wraps decorator on returned function (wrapper in your example), __doc__ attribute is copied from function f and overwrites whatever docstring you specify for wrapper.


答:
Don't just look at it from the point of view of the API, but also from the point of view of the client.

If I request http://example.org/users/52 as the client, there are a few things that are not unexpected: Total failure without even getting a status code (no network, https refused if it was https), status 401 or 500 (500 is always possible if the server is confused), but the two essential possibilities are that either the user does not exist, or that the user exists. And both would be handled by the client code in very different ways. That's way I would hope for either status 200 + the information that I want, or for status 404 (not found).

It's different if I have a search where any number of items could be returned, including zero, one, or many items. In that case I'd expect status 200 and an array of items, which might be an empty array. Status 404 I would expect if the API didn't ever get as far as searching. For example if I search for all purchases of user 52 from March to July, I'd expect status 404 if the user doesn't exist, and 200 if the user exists.

I don't know if the misspelling in a comment about usres/53 was intentional or not. This should give a status 404, or perhaps 400. In practice, the client isn't going to ask for that URL (once it is debugged and working properly). It is quite common for APIs to return a response together with the status, and in that case a response that clearly indicates that "usres" is not valid at all would be useful.

Title: JSON API specification : When do I need to return a 404 not found?

Body:
I'm working on a REST api following the JSON api specification and I'm struggling with the "no data" responses (described here).

A server MUST respond with 404 Not Found when processing a request to
  fetch a single resource that does not exist, except when the request
  warrants a 200 OK response with null as the primary data (as described
  above).

The "described above" refers to the previous section of the specification :

A server MUST respond to a successful request to fetch an individual
  resource with a resource object or null provided as the response
  document's primary data.

null is only an appropriate response when the requested URL is one
  that might correspond to a single resource, but doesn't currently.

I don't understand when I need to return a HTTP 404 Not Found and when I need with HTTP 200 OK with {"data":null}.

For example, if I have the following URL :

```<code>http://example.org/users/52
</code>```

This URL is correct, but the User referenced by the ID 52 doesn't exist.What is the correct response ? A 404 or a 200 data: null ?


问:
How to find the kth minimum element in an array
I am looking for an efficient algorithm to find the k'th minimum element in an unsorted array of n elements, where 1 <= k <= n. The obvious thing is to sort the array first, then pick the k'th element, which will result in a running time of O(n * log(n))  But I guess it can be done in a more efficient way, since sorting the array seems to do "too much". For example, for k=1 the task is to find the minimum of the array, which can be done in O(n).

Does anyone know  a better algorithm for k>=2?

答:
Examine the Quicksort algorithm carefully. Then consider that you want the k-largest element of the sorted array and don't care about any others, so in the Quicksort algorithm drop anything that will not affect the k-th element. In other words, don't sort any subarrays that don't contain the k-th element.

It's not optimal, but better than a complete sort.

You also might consider some tuning of the algorithm, just like Quicksort is usually tuned. What's optimal for Quicksort isn't always optimal for getting the k-th element.


问:
Which algorithm is performant for matrix multiplication of 4x4 matrices of affine transformations
I am wondering what is a good, performant algorithm for matrix multiplication of 4x4 matrices. I am implementing some affine transformations and I am aware that there are several algorithms for efficient matrix multiplication, like Strassen. But are there some algorithms that are especially efficient for matrices that small? Most sources I had a glance at are looking at which are asymptotically the most efficient.</p>

答:
Wikipedia lists four algorithms for matrix multiplication of two nxn matrices.

The classic one that a programmer would write is O(n3) and is listed as the "Schoolbook matrix multiplication".  Yep.  O(n3) is a bit of a hit.  Lets look at the next best one.

The Strassen algorithim is O(n2.807).  This one would work - it has some restrictions to it (such as the size is a power of two) and it has a caveat in the description:

Compared to conventional matrix multiplication, the algorithm adds a considerable O(n2) workload in addition/subtractions; so below a certain size, it will be better to use conventional multiplication.

For those who are interested in this algorithm and its origins, looking at How did Strassen come up with his matrix multiplication method? can be a good read. It gives a hint at the complexity of that initial O(n2) workload that is added and why this would be more expensive than just doing the classic multiplication.

So it really is O(n2 + n2.807) with that bit about lower exponent n being ignored when writing out big O. It appears that if you are working on a nice 2048x2048 matrix, this could be useful.  For a 4x4 matrix, its probably going to find it slower as that overhead eats up all the other time.

And then there's the Coppersmith–Winograd algorithm which is O(n2.373) with quite a few bits of improvements. It also comes with a caveat:

The Coppersmith–Winograd algorithm is frequently used as a building block in other algorithms to prove theoretical time bounds. However, unlike the Strassen algorithm, it is not used in practice because it only provides an advantage for matrices so large that they cannot be processed by modern hardware.

So, its better when you are working on super large matrixes, but again, not useful for a 4x4 matrix.

This is again reflected in wikipedia's page in Matrix multiplication: Sub-cubic algorithms which gets at the why of things running faster:

Algorithms exist that provide better running times than the straightforward ones. The first to be discovered was Strassen's algorithm, devised by Volker Strassen in 1969 and often referred to as "fast matrix multiplication". It is based on a way of multiplying two 2 × 2-matrices which requires only 7 multiplications (instead of the usual 8), at the expense of several additional addition and subtraction operations. Applying this recursively gives an algorithm with a multiplicative cost of O(nlog27) ≈ O(n2.807). Strassen's algorithm is more complex, and the numerical stability is reduced compared to the naïve algorithm, but it is faster in cases where n > 100 or so and appears in several libraries, such as BLAS.

And that gets to the core of why the algorithms are faster - you trade off some numerical stability and some additional setup. That additional setup for a 4x4 matrix is much more than the cost of doing the  more multiplication.

And now, to answer your question:

But are there some algorithms that are especially efficient for matrices that small?

No, there are no algorithms that are optimized for 4x4 matrix multiplication because the O(n3) one works quite reasonably until you start finding that you are willing to take a big hit for overhead. For your specific situation, there may be some overhead that you could incur knowing specific things beforehand about your matrixes (like how much some data will be reused), but really the easiest thing to do is write good code for the O(n3) solution, let the compiler handle it, and profile it later on to see if you actually have the code being the slow spot in the matrix multiplication.

Related on Math.SE: Minimal number of multiplications required to invert a 4x4 matrix


问:
Extreme Programming: how long are iterations supposed to be?
I was researching about Extreme Programming, and started reading a book by Kent Beck called Extreme Programming Explained. There he mentioned practices and principles one of which confused me. It said that iterations must short.

If iterations are good, we'll make the iterations really, really short - seconds and minutes and hours, not weeks and months and years (Extreme Programming Explained - Preface

Later on in the same book, Kent Beck uses iterations in weeks:

Within a release, XP uses one- to four-week iterations of customer-requested features for fine-grained feedback about progress. (Extreme Programming Explained - Chapter 1)

The glossary again mentions a 1-4 week iteraiton:

Iteration

A one- to four-week period. At the beginning, the customer chooses the
  stories to be implemented in the iteration. At the end the customer can run
  their functional tests to see if the iteration succeeded.

(Extreme Programming Explained - Glossary)

However when I read on the extreme programming website, it says that iterations are 1 - 3 weeks long. However, I found a video (starting at time 7:09) where it mentions iterations in days, minutes, and seconds.

In Extreme Programming, how long are iterations and how do they work? Does an iteration work on 1 user story for 2 weeks? That seems alot. One of the reasons this confuses me is because Scrum completes multiple user stories in one sprint which last for 2 weeks. When I further researched about that it said that developers prefer 2 week iterations. So which one is it? Am I confusing it with something else?

答:
I find this slightly confusing, but I think this one paragraph  in the preface (which is the only place in Kent Beck's book where iterations shorter than weeks are mentioned) helps clarify things:

When I first articulated XP, I had the mental image of knobs on a
  control board. Each knob was a practice that from experience I knew
  worked well. I would turn all the knobs up to 10 and see what
  happened. I was a little surprised to find that the whole package of
  practices was stable, predictable, and flexible.

The practices of Extreme Programming scale very well.

Let's take the example of The Planning Game. The Planning Game is done on both a release level (to plan the stories that will go into a release) and again at an iteration level (to plan the tasks that will be done in an iteration). In theory, you could continue using the Planning Game to plan and manage every activity - even an individual could use it to plan out their day, for example. However, at some point, it begins to not add value.

Extreme Programming really does take good software engineering practices to the extreme. Pair Programming is a core part of XP and it takes peer reviews and makes them continuous. Test Driven Development (TDD) encourages creating and frequently running unit tests (even before the code is written). Customers and users can provide feedback after each iteration, not just each release.

From a business perspective, it doesn't always make sense for a project to operate on iterations shorter than 1 week or longer than 4 weeks. Customer-visible iterations that are shorter than a week can be wasteful - you're frequently bringing the customer in to provide feedback on just about every minor change to the software. Longer than 4 weeks prevents responsiveness to changing requirements and the environment (you're less agile). But just because an iteration doesn't exist at the project level doesn't mean that the practices don't result in things being apparent to developers in minutes or seconds, where those things are the results of peer reviews (via Pair Programming), failed tests (unit testing / TDD), or builds (continuous integration). Some companies, though, like Google, Amazon, and Facebook (1, 2, 3, 4) can make changes live to customers multiple times a week, sometimes in seconds. These companies are at the most extreme end of Extreme Programming.


答:
The main reasons to clean up manually are: you’re less likely to mistake a genuine memory leak for a memory block that will just be cleaned up on exit, you will sometimes catch bugs in the allocator only when you walk the entire data structure to deallocate it, and you’ll have a much smaller headache if you ever refactor so that some object does need to get deallocated before the program exits.

The main reasons not to clean up manually are: performance, performance, performance, and the possibility of some kind of free-twice or use-after-free bug in your unnecessary clean-up code, which can turn into a crash bug or security exploit.

If you care about performance, you always want to profile to find out where you’re wasting all your time, instead of guessing.  A possible compromise is to wrap your optional clean-up code in a conditional block, leave it in when debugging so you get the benefits of writing and debugging the code, and then, if and only if you’ve determined empirically that it’s too much overhead, tell the compiler to skip it in your final executable.  And a delay in closing the program is, almost by definition, hardly ever in the critical path.


答: For 4x4 mat/mat multiplication, algorithmic improvements are often out. The basic cubic-time complexity algorithm tends to fare quite well, and anything fancier than that is more likely to degrade rather than improve times. Just in general, fancy algorithms are ill-suited if there isn't a scalability factor involved (ex: trying to quicksort an array that always has 6 elements as opposed to a simple insertion or bubble sort). Doing things like matrix transposition here to improve locality of reference also doesn't actually aid locality of reference when an entire matrix can fit into one or two cache lines. At this kind of miniature scale, if you are doing 4x4 mat/mat multiplication en masse, the improvements will generally come from micro-level optimizations of instructions and memory, like proper cache-line alignment.

Title: Which algorithm is performant for matrix multiplication of 4x4 matrices of affine transformations

Body: I am wondering what is a good, performant algorithm for matrix multiplication of 4x4 matrices. I am implementing some affine transformations and I am aware that there are several algorithms for efficient matrix multiplication, like Strassen. But are there some algorithms that are especially efficient for matrices that small? Most sources I had a glance at are looking at which are asymptotically the most efficient.</p>


问:
How narrow should my unit tests be?
Here's an example:

I have a chat module in my app, and there's a ChatService class that is responsible for networking, and there's a ChatNotificationService helper class that is responsible for sending out and receiving broadcasts of messages, and there's also a ChatNotificiationDelegate protocol that has methods on it that get called when a notification arrives.

In order to test message sending, in theory I could just call ChatService.sendMessage() and check if the ChatNotificationDelegate.didSentMessage() got called.

However, sending a message calls several different methods before it gets to the delegate. It sends the message to the server, the server then sends a response that triggers sending of the notification, and the notification service then receives the notification and calls the delegate method.

This whole chain can be covered by one unit test, or I could test each piece of functionality separately.

What I'm asking is which approach should I take on this, test every bit we know exactly what went wrong, or to make my tests as general as possible (just the endpoints) to allow more freedom of refactoring the code.

答:
You are comparing 2 kinds of tests: unit tests and integration tests. Unit tests should be fast. Myself, I like unit tests to run a fraction of a second. This matters when you run a test repeatedly while writing/changing code. To make unit test fast, your test can't call any remote resource or access a database. Most definitely, you don't want to start a chat server in your unit test.

Unit tests should also help you with refactoring. It's best done when your unit test only goes to the nearest architectural boundary. You test that you reach the boundary and hand correct message over the boundary. You may also check that your code correctly handles whatever may be returned from across the boundary. This way your system is loosely coupled and changeable - and so are your tests.

In addition to unit tests, you also test that your system interacts correctly across the boundaries and with other systems. People call these tests interaction or integration tests. They may take longer to run because they typically perform remote access and may even have to launch a test instance of a server. Because you already decoupled your layers in unit tests, you don't need to test every possible permutation of inputs and outputs in your integration tests. Each integration test runs longer, but you have fewer of them.

Putting it all together, I suggest that you create "small" unit tests for your ChatService, ChatNotificationDelegate and so on, going only as far as  the next service. You can mock the other service to verify that your test subject passes the right parameters across the boundary and reacts correctly to returns. You would aim to achieve a high coverage of unit tests. In addition, you will have a small number of integration tests that  each work across one boundary. Or maybe even a single end to end test of sending the message, as you suggested.

So my answer to

test every bit we know exactly what went wrong, or to make my tests as
  general as possible (just the endpoints) to allow more freedom of
  refactoring the code

is both: many small unit tests to know exactly what went wrong and one big integration test to be sure all pieces fit together. And I'd like to mention that a single end to end test doesn't "allow freedom of refactoring". The reverse is often true. Such a black box test can tell you that something is wrong, but you will have no idea what exactly broke. If system can break mysteriously, without an easy way to identify or at least pinpoint the root cause, you are more likely to fear making significant changes, such as refactoring.

Title: How narrow should my unit tests be?


答:
No, it is not necessary, but it's a Good Idea.

You say you feel that "mysterious and terrible things would happen if I didn't free memory after I'm done using it."

In technical terms, the only consequence of this is that your program will keep eating more memory till either a hard limit is reached (e.g. your virtual address space is exhausted) or performance becomes unacceptable. If the program is about to exit, none of this matters because the process effectively ceases to exist. The "mysterious and terrible things" are purely about the developer's mental state. Finding the source of a memory leak can be an absolute nightmare (this is an understatement) and it takes a lot of skill and discipline to write code that is leak-free. The recommended approach to developing this skill and discipline is to always free memory once it is no longer needed, even if the program is about to end.

Of course this has the added advantage that your code can be re-used and adapted more easily, as others have said.

However, there is at least one case where it is better not to free memory just before program termination.

Consider the case where you have made millions of small allocations, and they have mostly been swapped to disk. When you start freeing everything, most of your memory needs to get swapped back in to RAM so that the bookkeeping information can be accessed, only to immediately discard the data. This can make the program take a few minutes just to exit! Not to mention put a lot of pressure on the disk and physical memory during that time. If physical memory is in short supply to begin with (perhaps the program is being closed because another program is chewing up a lot of memory) then individual pages may need to be swapped in and out several times when several objects need to be freed from the same page, but are not freed consecutively.

If instead the program just aborts, the OS will simply discard all the memory that has been swapped to disk, which is nearly instantaneous because it doesn't require any disk access at all.

It's important to note that in an OO language, calling an object's destructor will also force the memory to be swapped in; if you have to do this you might as well free the memory.