在 C&C++ 中查找未初始化的变量

Find uninitialized variables in C&C++

本文关键字:初始化 变量 查找 C++      更新时间:2023-10-16

我的意思是C和C++。这个项目正在使用 C 中的 lib,它正在C++调用我的函数。但是,这些函数在外部"C"中,因为库需要它。

无论如何,在这些函数中,我确实new Blah.当调用特定函数(end_tree)时,我希望初始化所有变量。使用Visual Studios,GCC或任何其他编译器,我有没有办法检查?我只是注意到一些布尔值是真的,这不应该是......为什么,因为它没有初始化。我可以使用某种_VS_CheckThisMemory(mytree)功能或魔法吗?

不知道这是你想要的,但gcc-Wmaybe-uninitialized-Wuninitialized。警告选项页面上可能还有更多内容。

使用 valgrind(在 Linux 上)

./valgrind myprogram

当myprogram使用调试信息(gcc -g)编译时特别容易,但不是必需的。Valgrind 将通知正在使用未初始化的内存的位置,以及从何处分配内存。如果它有调试信息,valgrind 将准确报告发生在哪个文件:行号上。(它甚至可以即时附加调试器,以便您进行调试

它还将检测超出分配边界的访问和释放后的访问。这是非常有用的。

这里结束有用的答案


编辑,因为不清楚我为什么要发布以下内容,正如评论中可以清楚地看出的那样,让我介绍这个答案的其余部分:

当开始使用现有代码库的valgrind时,几乎不可避免地会得到"假"阳性,即(还)不是真正问题的报告。我包括一个可能触发此类报告的示例,以及您通常如何解决这些问题。

我只是为了提高对如何处理或识别(半)误报的认识。

另一种措辞方式(参考马修在评论中令人信服的推理)是将瓦尔格林德的警告视为关键:修复它们,而不是忘记它们

valgrind 可能会在不是真正问题时报告未初始化的访问。比如,例如

 char buf[1024];
 strcpy(buf, "hello");
 char clone[1024];
 memcpy(clone, buf, 1024);

你应该通过做一些更聪明的事情来解决这个问题,比如

 memcpy(clone, buf, strlen(buf));

确保 buf 中没有未初始化的"部件"(或至少在访问的区域中没有)

使用自初始化类来覆盖那些烦人的原语。

template<typename T> class always_initialized {
    T t;
public:
    always_initialized()
        : t(T()) {}
    always_initialized(const T& ref) {
        : t(ref) {}
    operator T&() { return t; }
    operator const T&() const { return t; }
    T& operator=(const T& ref) { return t = ref; }
};

为了响应注释中链接的代码,RAIIIA ( Resource Acquisition is Initialization In Action (R)

class OtherClass;
class MyClass : public SomeBase {
public:
    // note I got rid of your default constructor, which leaves values unitialized
    MyClass(Var* name, OtherClass* loop)
    :   m_name(name), m_loop(loop) // this right here
    {   }
    virtual ~MyClass(); // no implementation needed here
    void save();
    // made the members protected, other classes have no business accessing them directly
protected:
    Var* m_name;
    OtherClass* m_loop;
};

您的默认构造函数将值保留为单位化,并以纯形式与 RAII 背道而驰。这样做是可以的,但是由于您在未初始化的变量方面遇到问题,我会重新评论删除默认构造函数。

编辑:将未知指针存储为类成员而不new并在类构造函数/析构函数中delete它们并不是真正的 RAII,但我希望你在某个地方这样做。

我通过使用带有模板的解决方案来充当属性来解决此问题。我在C++中使用了类似属性的功能?但是还有其他例子可以做其他事情,比如传入 get/setter。

基本上生成了

我能够生成的大部分代码 bc,并且我跟踪是否通过属性设置了变量。最后,我只是检查成员并断言告诉我是否设置了变量。我也断言当我"得到"以防万一。