-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HAVE_SNPRINTF and MSVC std::snprintf support #80201
Comments
Abstract: pyerrors.h defines snprintf as a macro on MSVC even on versions of MSVC where this workaround causes bugs. snprintf is defined as _snprintf in pyerrors.h, see: Lines 326 to 330 in ac28147
The conditions for this should exclude _MSC_VER >= 1900 where (std::)snprintf is correctly defined. Since this is not the case, subsequent user code that tries to use std::snprintf will fail with an err (_snprintf is not a member of namespace std). |
I don't have MSVC because on I work on Linux. Could tell me if this PR fixes your issue? Thank you |
@steve.dower, @zach.ware I don't have a Windows machine, I could install an official VM of Windows and install MSVC but I don't have time, I am working for my customer but I could check my PR later (I will wait for the feedback of AppVeyor). Thank you for your feedback, |
For the version of MSVC, I have found this link: |
Hi, Do you suggest if this VM is correct for the tests? I will try to check with this one. https://developer.microsoft.com/en-us/windows/downloads/virtual-machines |
It works on my machine. ;) I would also add a check for #if defined(MS_WIN32) && !defined(HAVE_SNPRINTF) && defined(_MSC_VER) && _MSC_VER < 1900
or #if defined(MS_WIN32) && !defined(HAVE_SNPRINTF) && (!defined(_MSC_VER) || _MSC_VER < 1900)
I don't know whether (MS_WIN32 && !defined(_MSC_VER)) means that there is an The VMs seem OK to me for testing. |
I have the following internal, almost-minimal test case for this bug. It also relies on Boost Python, but that could be eliminated to produce a similar test case. # CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(python-boost-mcve)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost COMPONENTS python36 REQUIRED)
find_package(Python3 COMPONENTS Development REQUIRED)
add_library(python-boost-mcve)
target_link_libraries(python-boost-mcve PUBLIC Python3::Python Boost::python36)
target_sources(python-boost-mcve PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/python-boost-mcve.cpp") // python-boost-mcve.cpp
// 1. This is a bug with MSVC Python
#if !defined(_MSC_VER) || _MSC_VER < 1900
# error "The MCVE requires Visual Studio 14.0 or higher"
#endif
// 2. An MSVC system header is required to reproduce the error for some reason,
// perhaps it sets some macro. This needs to be BEFORE <boost/python.hpp>
#include <array>
// 3. Boost Python is required to include the system (MSVC) Python headers that
// define _snprintf as a macro under the circumstances
// #define HAVE_SNPRINTF // Define this macro as a workaround to fix the compile error
#include <boost/python.hpp>
// 4. Now we can observe that the following function won't compile
#include <cstdio>
void test() {
char buf[2];
std::snprintf(buf, 1, "x");
// error C2039: '_snprintf': is not a member of 'std' [python-boost-mcve.vcxproj]
} |
For the record, I am basing the version check code on Boost also: https://www.boost.org/doc/libs/1_65_1/boost/convert/detail/config.hpp |
We don't support older versions of MSVC at this point, so the version check seems unnecessary. If we need to alias these within the CPython sources for non-MSVC compilers, then we should do it in source files. In general, we never want to pollute the user's namespace with aliases like this - when we do, it should get a "_Py_" prefix and ideally be behind one of the Py_BUILD_CORE variables. So I'd rather see a change to remove those definitions from the header files and put them closer to where they belong. If that's too many places, they can go into an internal header with "_Py_" prefix and update all uses. |
Hi @Steve I'm not used to this, can you guide me? |
Start by just deleting the definitions in pyerrors.h, and see where the build fails. Then either switch those to use PyOS_snprintf (best), or add the #ifndef checks in the source files (not header files) that need them. Be aware that we shouldn't backport the deletion from the headers to 3.7. Backporting the code changes to use the PyOS_* functions is fine though. |
I will continue to work on this issue when I will have a Windows virtual machine or a computer, for the moment I close my PR because it's not the right solution. Sorry for my inactivity about this issue. |
I wrote PR 20889 which removes "snprintf" and "vsnprintf" macros from pyerrors.h. I propose to backport the change to 3.9, but leave 3.8 unchanged. On Python 3.8 and older, the workaround is to manually undefine the macros: #include <Python.h>
// Undefine macros to work around https://bugs.python.org/issue36020
#undef snprintf
#undef vsnprintf |
In April, the issue was discussed on the capi-sig mailing list: This issue was also mention in: |
pybind11 implemented a different workaround: /* Don't let Python.h #define (v)snprintf as macro because they are implemented
properly in Visual Studio since 2015. */
#if defined(_MSC_VER) && _MSC_VER >= 1900
# define HAVE_SNPRINTF 1
#endif |
Can't we just use #ifndef __cplusplus instead of changing the function? I don't think anyone compiles the affected files with a C++ compiler. There are many areas in Include/* that fail with C++, e.g. isnan() with -std=c++11. |
I've tested the MSVC _snprintf extremely extensively in _decimal and never had a problem. |
I removed the two offending macro defines from Python.h (pyerrors.h) in 3.9 and master branches. I close the issue. I also simplified PyOS_snprintf() and PyOS_vsnprintf() implementation in the master branch: they no longer call Py_FatalError() on buffer overflow, on platforms which don't provide vsnprintf(). vsnprintf() is now required to build the master branch. |
- python/cpython#80201 - Fixes Phenix Windows builds for Python 3.8 and lower
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: