Failing to include external _Py_DECREF_DecRefTotal referenced in function Py_DECREF

This is my first time using the C API in python and I am slightly puzzled, In Release mode i can build and run my application completely fine, however in debug mode i get an unresolved external symbol to a specific function. I have tried on earlier versions and this function changes, i am guessing its to do with the way I get around not having the debug libraries

#pragma once

#define MS_NO_COREDLL
#include <Python.h>

I have tried the method of undefining _DEBUG then redefining it but that just gives me a bunch of errors. I have been researching and those are the only two I have found. If anyone has anything else I can try please let me know, if more code is needed let me know, thank you!

1 Like

Personally, I debug by making a release build with optimisations turned off in the compiler so that I can single step through my code more easily.

It might be worth defining Py_DEBUG as well. But I’m not sure if you should really have to do that

Is it a Python API function? Which one?

It is a python api function, for my version of python its _Py_DECREF_DecRefTotal specifically from Py_DECREF

I have tried this and it works, however even though optimizations are turned off and I can step through the code easily debug mode has extra checks for things like heap/stack overflows and other extra checks with debug so this isn’t an ideal solution by any means but thank you.

(You didn’t specify, but I assume from the MS_NO_COREDLL that you’re on Windows. We also treat the use of that variable as stating “I know what I’m doing,” which is why you aren’t getting a more helpful error message :wink: )

A true debug build (_DEBUG defined) will try to link against python3XX_d.dll rather than python3XX.dll, because of those additional functions. By disabling automatic linking and presumably setting it yourself, you are not going to get a working build.

Your easiest fix is to build in a Debug configuration but change the C runtime option to non-debug (/MD rather than /MDd, as described here), and to link to the regular python3XX.lib rather than the debug (_d) one. This will lose assertions from within the C runtime library, but your own code should still have them all, as well as other runtime checks.

Alternatively, you can start from a Release configuration, disable optimisations, and activate all the additional runtime checks. They are all compiler options set under a default profile - the compiler itself has no concept of this kind of preset, so you can change everything you need.

I personally tend to use the latter approach (typically just disabling optimisations and increasing debug info) as I don’t rely on assertions much, but I documented the first approach as it’s closer to the “normal” experience.


Two final options are to install Python from the installer on python.org, go through advanced options, and enable debug binaries and symbols on the last page. This will give you a pre-built (though unsigned) python3XX_d.dll to link against so you can debug into Python itself, but also use the full set of debug settings for your own code. It does mean you need to launch python_d.exe instead of python.exe, but that may not matter.

And finally, you can build Python from source PCbuild\build.bat -d to get a debug build, which is likely even harder to use than the installed one, but if you’re having to debug Python itself then it’s invaluable.

But it seems like you only need to debug your own code, and so there’s not going to be much gained from a debug build of Python. If/when it crashes in the runtime itself, walk up the stack to your own code to see what you passed in, and try to guess from that what may have gone wrong (typically reference count issues) - stepping through Python’s own code is less likely to be helpful than starting with your own.