# Delete() doesn't release memory?

**URL:** https://discourse.vtk.org/t/delete-doesnt-release-memory/9642
**Category:** Support
**Created:** [October 19, 2022, 12:11am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642 "2022-10-19T00:11:38Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [October 19, 2022, 12:11am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/1 "2022-10-19T00:11:38Z")

</div>

Hi VTK experts,

I have a number of image stacks of which I need to crop a VOI out after I assemble them. I used `vtkImageAppend* volumeAppend = vtkImageAppend::New()` to assemble these stacks forming one single volume. Then I used `vtkExtractVOI* voi = vtkExtractVOI::New()` to get the VOI I wanted. Once I got the VOI, `volumeAppend` became no use anymore and I intended to release the memory held by it. However, calling `volumeAppend->Delete()` doesn’t seem to release the memory according to Visual Studio’s diagnostic tool. Moreover, I called `volumeAppend->GetOutput()->GetActualMemorySize()` and the return value was the same as it was before `volumeAppend->Delete()`. Eventually I found that I could use `volumeAppend->ReleaseDataFlagOn()` to free up the memory.

But it left me confused: Why `Delete()` doesn’t seem to do the job? Could someone enlighten me a little about some details behind it?

Thanks so much!

PS. To provide a little more context, I used `vtkTIFFReader` to read in those stacks, and called `volumeAppend->AddInputConnection()` to take vtkTIFFReader’s `GetOutputPort()` to assemble the stacks.

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [October 19, 2022, 12:46am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/2 "2022-10-19T00:46:52Z")

</div>

Hi @MKRangers

Please share actual code, it is hard to follow in its current form.

In any case, the data handled by the filter will pass through the pipeline and will only be released once it is not needed by anyone using reference counting.

But, the following is NOT valid code:

```auto
vtkImageAppend* volumeAppend = vtkImageAppend::New()
volumeAppend->Delete()
volumeAppend->AnyMethod()

```

After the delete, volumeAppend has been deleted, even if some of the data it handled have been passed to another class.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [October 19, 2022, 2:05pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/3 "2022-10-19T14:05:57Z")

</div>

Note that `Delete` would be better named `ReleaseReference`. And yes, calling methods through a pointer that you’ve released the reference of is “getting lucky” when it works (you’re firmly in UB territory).

---

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [October 19, 2022, 5:32pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/4 "2022-10-19T17:32:29Z")

</div>

Hi @mwestphal

Thank you for your quick reply. Indeed, calling a method after Delete() and still got a value returned is another puzzling thing for me. Seeing the memory still being held after Delete() is what prompted me to call GetActualMemorySize() because I suspected Delete() wasn’t doing what I thought it was doing. The following is my actual code:

Note, `ArboretaVolumeSP` is a `std::shared_ptr` of `ArboretaVolume` class in which a `vtkImageAppend*` member `mVolumeAppender` resides. The method `ArboretaVolumeProcessor::teraflyVolumeAssemble()` is where stack assembling happens:

```auto
ArboretaVolumeSP ArboretaVolumeProcessor::teraflyVolumeAssemble(const vector<vector<vector<string>>>& teraflyStackNamesRange)
{
	ArboretaVolumeSP outputArbVolume(new ArboretaVolume);
	
	outputArbVolume->mVolumeAppender = vtkImageAppend::New();
	outputArbVolume->mVolumeAppender->SetAppendAxis(1);
	for (vector<vector<vector<string>>>::const_iterator yDirIt = teraflyStackNamesRange.cbegin(); yDirIt != teraflyStackNamesRange.cend(); ++yDirIt)
	{
		vtkImageAppend* xzAppend = vtkImageAppend::New();
		xzAppend->SetAppendAxis(0);
		for (vector<vector<string>>::const_iterator xDirIt = yDirIt->cbegin(); xDirIt != yDirIt->cend(); ++xDirIt)
		{
			vtkImageAppend* zAppend = vtkImageAppend::New();
			zAppend->SetAppendAxis(2);
			for (vector<string>::const_iterator zFilenameIt = xDirIt->cbegin(); zFilenameIt != xDirIt->cend(); ++zFilenameIt)
			{
				vtkTIFFReader* inputReader = vtkTIFFReader::New();
				inputReader->SetFileName((*zFilenameIt).c_str());
				inputReader->SetDataSpacing(1, 1, 1);
				inputReader->SpacingSpecifiedFlagOn();
				inputReader->Update();

				zAppend->AddInputConnection(inputReader->GetOutputPort());
				inputReader->ReleaseDataFlagOn(); // No memory reduction observed without it.
				inputReader->Update();
				inputReader->Delete(); 
			}
			zAppend->Update();

			xzAppend->AddInputConnection(zAppend->GetOutputPort());
			zAppend->ReleaseDataFlagOn();
			zAppend->Update();
			zAppend->Delete();
		}
		xzAppend->Update();

		outputArbVolume->mVolumeAppender->AddInputConnection(xzAppend->GetOutputPort());
		xzAppend->ReleaseDataFlagOn();
		xzAppend->Update();
		xzAppend->Delete();
	}
	outputArbVolume->mVolumeAppender->Update();

	return outputArbVolume;
}

```

As you can see, I called `ReleaseDataFlagOn()` in every layer of for loop in order to see memory usage reduction. There was no such phenomenon observed if only `Delete()` was called without `ReleaseDataFlagOn()`.

Here’s the caller of the method above:

```auto
ArboretaVolumeSP wholeBrainVolume = ArboretaVolumeSP(new ArboretaVolume);
if (mFormat == volumeFileFormat::tif || mFormat == volumeFileFormat::tiff)
{
	wholeBrainVolume->mVolumeAppender = vtkImageAppend::New();

	wholeBrainVolume = this->mTeraflyVolumeProcessor.teraflyVolumeAssemble(lowestResFilenameTree);
    cout << wholeBrainVolume->mVolumeAppender->GetOutput()->GetActualMemorySize() << endl; // returns value xyz

	wholeBrainVolume->rescaleDynamicRange();
	wholeBrainVolume->mVolumeAppender->ReleaseDataFlagOn();
	wholeBrainVolume->mVolumeAppender->Update();
	wholeBrainVolume->mVolumeAppender->Delete();	
	cout << wholeBrainVolume->mVolumeAppender->GetOutput()->GetActualMemorySize() << endl; // still returns value xyz!?
}

```

In the above section, `rescaleDynamicRange()` is a method I implemented to convert the 16 bit volume to 8 bit by using `vtkImageShiftScale` with `SetInputConnection(mVolumeAppender->GetOutputPort())`. Again, I needed to call `ReleaseDataFlagOn()` to see memory use reduction, and even after I called `Delete()`, I still got to see same value returned by `GetActualMemorySize()` before and after `Delete()`.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [October 19, 2022, 5:46pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/5 "2022-10-19T17:46:27Z")

</div>

If you run under `valgrind` or some other memory checker, does it complain about use-after-free? Again, I think you’re just getting lucky and code is using garbage memory that happens to still have useful values in it.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 19, 2022, 6:31pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/6 "2022-10-19T18:31:35Z")

</div>

Hi @MKRangers,

As Ben mentioned, `Delete()` simply releases a reference to the object, it doesn’t always delete the object. Modern VTK programming style prefers smart pointers (`vtkNew<>` and `vtkSmartPointer<>`) to automatically release the reference, rather than using `Delete()` to release the reference.

Also, `append->AddInputConnection(reader->GetOutputPort())` causes `append` to reference `reader` and, for memory efficiency, inter-object references should be avoided unless they are needed. So you can re-write your code like this:

```cpp
  {
    // vtkNew<> is like std::unique_ptr<>
    vtkNew<vtkTIFFReader> inputReader;
    inputReader->SetFileName((*zFilenameIt).c_str());
    inputReader->SetDataSpacing(1, 1, 1);
    inputReader->SpacingSpecifiedFlagOn();
    inputReader->Update();

    // get the reader's output (we don't want to create a connection)
    zAppend->AddInputData(inputReader->GetOutput());
  }

```

But the `zAppend` is probably not needed at all, because one `vtkTIFFReader` is able to read a stack of images and generate a volume all by itself. Just use `reader->SetFileNames(vtkStringArray*)` instead of `reader->SetFileName(const char*)`.

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [October 19, 2022, 10:33pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/7 "2022-10-19T22:33:27Z")

</div>

Does **wholeBrainVolume** add additional references to _vtkImageAppend_ inside the setter method?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [October 20, 2022, 11:39am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/8 "2022-10-20T11:39:56Z")

</div>

Even if it does today, there’s no guarantee of that. You should not use pointers to which you do not have a definitive reference to (i.e., post-`Delete()`).

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [October 20, 2022, 9:43pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/9 "2022-10-20T21:43:05Z")

</div>

I totally agree. Dereferencing an object and then trying to invoke its methods is asking for trouble. I was encouraging @MKRangers to investigate the reason for the anomaly in this case.

---

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [October 21, 2022, 5:40am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/10 "2022-10-21T05:40:00Z")

</div>

Hi @dgobbi ,

Thank you for your advice. I checked VTK document, `vtkTIFFReader->SetFileNames(vtkStringArray*)` can only take image slices, but each file I’m working with is a 3D stack already, so I guess I still need to use `vtkImageAppend`.

To be honest, I’m a VTK newbie here and I don’t quite understand the difference between the pairs of `AddInputConnection()` - `GetOutputPort()` and `AddInputData()` - `GetOutput()`. Could you please explain a bit?

I did a little experiment comparing the memory usage between these 2 methods, no difference found by the end of `teraflyVolumeAssemble()`. However, when the method returns back to its caller, using `AddInputConnection()` - `GetOutputPort()` shows substantially less memory occupied than `AddInputData()` - `GetOutput()` (1 GB vs 1.6 GB). After rendering it, it becomes 1.5 GB and 2.1 GB, respectively.

---

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [October 21, 2022, 6:15am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/11 "2022-10-21T06:15:23Z")

</div>

Hi @ben.boeckel and @toddy,

Actually, `wholeBrainVolume` doesn’t add additional reference. But the fact that `Delete()` only releases the reference makes sense to me now. As I mentioned in 1 of my previous replies, I used a `vtkImageShiftScale` to `SetInputConnection()` from `wholeBrainVolume`’s `vtkImageAppend` member. This is where the additional reference takes place, and that’s why I got the anomaly. I did get read access violation if I skipped this step.

But again, the reason I called some method after `Delete()` is because I suspected `Delete()` didn’t destroy the object and I wanted to see if I still could get something after I called it. Now I got my answer, thank you very much!

Now another VTK newbie question for you if you don’t mind. When I checked the reference count, `vtkImageAppend->GetReferenceCount()` already returned 2 when it was created while `vtkImageAppend->GetOutput()->GetReferenceCount()` returned 1. What’s the difference and what is that?

Thank you again!

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 21, 2022, 6:32pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/12 "2022-10-21T18:32:20Z")

</div>

To understand the difference between `SetInputConnection()` and `SetInputData()`, it’s necessary to understand the VTK pipeline executive. Every “Algorithm” object in VTK is paired with an “Executive” object. When you call `algorithm->Update()`, it simply does `algorithm->Executive->Update()`, and then the Executive manages the actual execution of the Algorithm. Confusing, right? The idea is that the Executive is in control of the Algorithm, even though the Executive is mostly invisible to the user.

One important thing that the Executive does, is that it manages connections between Algorithms. When you do this

```cpp
   append->AddInputConnection(reader->GetOutputPort());

```

the result is that the Executive of “append” holds not only a reference to “append” itself, but also a reference to “reader”. And if you call `append->Update()`, the Executive will automatically update “reader” as well.

In comparison, if you do this

```cpp
append->AddInputData(reader->GetOutput());

```

then the Executive doesn’t know anything about “reader”, all it gets is the reader’s output (which must already be up-to-date before “append” is updated). More details can be found on the [Kitware blog](https://www.kitware.com/a-vtk-pipeline-primer-part-1/).

In general, if you only plan to update an algorithm once, you should call `Update()` and then `GetOutput()`, but if you plan to update an algorithm over and over as part of a pipeline, then you should call `GetOutputConnection()` and let the executive handle the updates.

I don’t know why you are seeing more memory usage with `GetOutput()` than with `GetOutputPort()`, it doesn’t make sense to me. I’d have to see the exact code that you used to test the memory usage.

With respect to `ReleaseDataFlag`, it just controls whether the algorithm releases its reference to the data object, so it doesn’t guarantee that the memory is released. The data is not “owned” by just one algorithm, since it exists both as the output of one algorithm, and as the input of other algorithms, all of which hold references to it via their executives.

(If it wasn’t already obvious, the VTK pipeline architecture can be crazy complicated).

---

<div class="post-metadata">

### Author: ![toddy](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/t/edb3f5/32.png) [@toddy](https://discourse.vtk.org/u/toddy)
#### Post date: [October 21, 2022, 10:25pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/13 "2022-10-21T22:25:40Z")

</div>

> [@MKRangers](#):
>
> When I checked the reference count, `vtkImageAppend->GetReferenceCount()` already returned 2 when it was created while `vtkImageAppend->GetOutput()->GetReferenceCount()` returned 1. What’s the difference and what is that?

The class documentation [VTK: vtkImageAlgorithm Class Reference](https://vtk.org/doc/nightly/html/classvtkImageAlgorithm.html#afe91957f0c43e0a891a9f002c676f45e) shows that `vtkImageAppend->GetOutput()` returns **vtkImageData** ; a completely different object.

---

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [October 28, 2022, 4:15pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/14 "2022-10-28T16:15:17Z")

</div>

I understand. I guess my real question is why `vtkImageAppend->GetReferenceCount()` returns 2 even there is obviously only one using count? It’s like the first instanced object already takes 2.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [October 28, 2022, 5:32pm UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/15 "2022-10-28T17:32:25Z")

</div>

What version of VTK are you using? I did a bit of experimenting with the latest release, and found that the ‘executive’ object (which I mentioned in my post above) is responsible for the additional reference count. In Python:

```python
>>> import vtkmodules
>>> vtkmodules. __version__'9.2.2'
>>> from vtkmodules.vtkFiltersCore import vtkImageAppend
>>> a = vtkImageAppend()
>>> a.GetReferenceCount()
1
>>> # when the filter creates an executive, the reference count increases
>>> e = a.GetExecutive()
>>> a.GetReferenceCount()
2
>>> # likewise, the executive has a reference count of 2
>>> e.GetReferenceCount()
2
>>> # add an observer so we know when the filter is deleted
>>> a.AddObserver('DeleteEvent', print)
>>> # release our references to both objects, and the filter is deallocated
>>> del a
>>> del e
None DeleteEvent

```

So for VTK 9.2.2, at least, the extra reference count doesn’t appear until something causes the algorithm’s ‘executive’ to be created.

If I do the same experiment, but don’t hold the reference to the executive after calling `GetExecutive()`, then deleting the reference to the algorithm successfully deallocates the algorithm, even though it had a reference count of two. This works because VTK’s garbage collection can handle reference cycles.

```python
>>> from vtkmodules.vtkFiltersCore import vtkImageAppend
>>> a = vtkImageAppend()
>>> a.GetExecutive()
<vtkmodules.vtkCommonExecutionModel.vtkCompositeDataPipeline(0x7ff9b3425f20) at 0x7ff9a84b3588>
>>> a.GetReferenceCount()
2
>>> # add an observer
>>> a.AddObserver('DeleteEvent', print)
>>> # release our reference
>>> del a
None DeleteEvent

```

* * *

Edit: I checked, and VTK has behaved this way all the way back to VTK 5, so I guess the version of VTK that you are using is a moot point.

An algorithm has a reference count of 1 when first created, and the reference count increases to 2 as soon as the executive is created. The executive is created when you call `SetInputData()`, `SetInputConnection()`, `GetOutput()`, `GetOutputPort()`, `Update()`, `GetExecutive()`, or any of the many other algorithm methods that require an executive.

---

<div class="post-metadata">

### Author: ![MKRangers](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mkrangers/32/5341_2.png) [@MKRangers](https://discourse.vtk.org/u/MKRangers)
#### Post date: [November 15, 2022, 5:40am UTC](https://discourse.vtk.org/t/delete-doesnt-release-memory/9642/16 "2022-11-15T05:40:24Z")

</div>

My VTK version is 9.1. Anyway, I know it’s been late, but I shall at least reply to show my appreciation of your time and informative posts. Once again, thank you very much. I learned a lot here.
