如何在使用Py_BEGIN_ALLOW_THREADS时避免Python C扩展中的gcc警告

7 投票
3 回答
1047 浏览
提问于 2025-04-15 18:32

在Python的C扩展中,处理全局解释器锁(GIL)最简单的方法就是使用提供的宏:

my_awesome_C_function() 
{
    blah;

    Py_BEGIN_ALLOW_THREADS

    // do stuff that doesn't need the GIL

    if (should_i_call_back) {
        Py_BLOCK_THREADS
        // do stuff that needs the GIL
        Py_UNBLOCK_THREADS
    }

    Py_END_ALLOW_THREADS

    return blah blah;
}

这样做效果很好,我可以在大部分代码中释放GIL,但在一些需要它的小代码段中再重新获取。

问题是,当我用gcc编译这个代码时,我收到了以下错误:

ext/engine.c:548: warning: '_save' might be used uninitialized in this function

这是因为Py_BEGIN_ALLOW_THREADS的定义方式是这样的:

#define Py_BEGIN_ALLOW_THREADS { \
        PyThreadState *_save; \
        _save = PyEval_SaveThread();

所以,我有三个问题:

  1. 有没有办法抑制gcc的警告,
  2. 有没有人知道为什么gcc认为_save可能会被未初始化使用,因为它在声明后马上就被赋值了,
  3. 为什么这个宏没有被定义成在一个语句中声明并初始化变量,以避免这个问题呢?

(最后两个问题其实只是出于我自己的好奇)。

我可以通过不使用这些宏,自己处理所有的事情来避免这个问题,但我更希望不这样做。

3 个回答

0

Ned,你可以试试这些方法

#pragma GCC diagnostic warning "-Wno-unitialized"
#pragma GCC diagnostic error "-Wno-uninitialized"
#pragma GCC diagnostic ignored "-Wno-uninialized"

或者忽略-Wuninitialized这个警告?根据说明,你需要在定义任何数据或函数之前这样做。也许这样可以让你只在那个文件中关闭这个警告?

1

我来分享一下我的看法:

  1. 你可以选择忽略特定的警告,不过我想你可能已经知道这一点了。
  2. 它说这个变量可能没有被初始化 :-)
  3. 我能想到的唯一原因是为了和老旧的C编译器兼容。

我尝试去查找一下源代码,但没找到什么有用的线索。

3
  1. 是的,可以通过使用 -Wno- 前缀来抑制未初始化的警告。

-Wall -Wno-uninitialized

如果你只想去掉这个警告,可以简单地把 _save 初始化为一个空指针,这样它就不需要依赖函数的返回值了……这一行代码和一个注释对我来说是有意义的:

PyThreadState *_save; 
_save = 0; /* init as null pointer value */
_save = PyEval_SaveThread();

撰写回答