Issue 1:
The pyfragments.swg file which is shipped with numpy contains a memory leak in the redefinition of SWIG_CanCastAsInteger for long and unsigned long. The PyArray_Desc pointer which is created near the top of the function is not DECREFed when the function returns. Furthermore, the pointer is created very far away from where it is actually used.

Reproducing code example:

The problem can be reproduced with the following:

A cmake file for building this example (CMakeTexts.txt):

CMAKE_MINIMUM_REQUIRED(VERSION 2.6.2)

# Set up libfoo
add_library(foo
bar.cpp
)
add_definitions(-fPIC)
target_link_libraries(foo)

# Set up swig
SET(InterfaceFile foo.i)

FIND_PACKAGE(SWIG 3 REQUIRED)
INCLUDE(${SWIG_USE_FILE})

SET(CMAKE_SWIG_FLAGS -c++)

# Get the python site-packages directory
EXECUTE_PROCESS(COMMAND python -c "import site; print(site.getsitepackages()[0])"
OUTPUT_VARIABLE PYTHON_SITE
OUTPUT_STRIP_TRAILING_WHITESPACE)

# INCLUDE SOURCE
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} )
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} )

# PYTHON DIRECTORIES
INCLUDE_DIRECTORIES( SYSTEM /path/to/include/python2.7 )
LINK_DIRECTORIES( /path/to/lib/python2.7/ )

# NUMPY INCLUDES
INCLUDE_DIRECTORIES( SYSTEM ${PYTHON_SITE}/numpy-1.15.1-py2.7-linux-x86_64.egg/numpy/core/include/ )

SET_SOURCE_FILES_PROPERTIES(${InterfaceFile} PROPERTIES SWIG_MODULE_NAME Foo)
SET_SOURCE_FILES_PROPERTIES(${InterfaceFile} PROPERTIES CPLUSPLUS ON)

SET(SWIG_MODULE_Foo_EXTRA_DEPS
bar.h
)
SWIG_ADD_MODULE(Foo python ${InterfaceFile})

SWIG_LINK_LIBRARIES(Foo ${PythonFramework} foo)
SET(DLLSuffix so)

A c++ header file which will be wrapped by swig (bar.h):

#include <vector>

class Bar
{
public:
Bar(int length);

double data(int index);

private:
std::vector<double> data_;

};

The respective source file (bar.cpp):

#include "bar.h"

Bar::Bar(int length)
: data_(length)
{
}

double Bar::data(int index)
{
return data_[index];
}

The swig interface file (foo.i):

%module Foo

%{
#include "numpy/arrayobject.h"
#include "bar.h"
%}

%include "numpy.i"

%init
%{
import_array();
%}

%include "bar.h"

Once all of these folders are inside a folder, make sure to copy the numpy.i and pyfragments.swg over from your numpy-1.15.1/tools/swig. Then run mkdir build && cd build && cmake .. && make.

Then once the swig wrapper has been created, the following python script can be executed:

import Foo

def main():
foo = Foo.Bar(1)

while True:
foo.data(0)

if __name__ == '__main__':
main()

You can run the example python file with PYTHONPATH=${PYTHONPATH}:$(pwd) ../test.py.

If the pyfragments.swg file was located in the source tree when the swig module was built, then running the example will show a memory leak. If it was not present, then there will be no memory leak.

Numpy/Python version information:

Numpy version: 1.15.1

Python version: 2.7.11

Output from 'import sys, numpy; print(numpy.version, sys.version)':

('1.15.1', '2.7.11 (default, Sep 3 2018, 11:28:21) \n[GCC 5.4.0 20160609]')

Issue 2:
I think I found a memory leak in pyfragments.swg. In both SWIG_AsVal_dec fragments, PyArray_DescrNewFromType is called but its return value may not get deallocated.

I moved the calls to PyArray_DescrNewFromType to right before their value is used (the calls to PyArray_CastScalarToCtype) and added a call to Py_DECREF and that seems to have fixed my memory leak.

I discovered this in numpy 1.4.1, but I checked 1.9.0 and I think it's still present there.