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

发布于 2024-11-06 07:23:15 字数 294 浏览 1 评论 0原文

我真正的意思是 C 和 C++。该项目使用 C 语言的库,该库正在 C++ 中调用我的函数。然而,这些函数位于 extern“C” 中,因为库需要它。

不管怎样,在这些函数中我做了new Blah。当调用特定函数(end_tree)时,我希望所有变量都被初始化。使用 Visual Studios、GCC 或任何其他编译器我可以检查吗?我只是注意到有些布尔值是 TRUE,这不应该是......为什么,因为它没有初始化。我可以使用某种 _VS_CheckThisMemory(mytree) 函数或魔法吗?

I really mean C and C++. This project is using a lib in C which is calling my functions in C++. However the functions are in extern "C" because the lib expects it.

Anyways, in these functions I do new Blah. When a specific function is called (end_tree) i expect all my variables to be initialized. Using Visual Studios, GCC or any other compiler is there a way i can check? I just notice some bools are TRUE which shouldn't be... why, because it wasn't initialized. Is there some kind of _VS_CheckThisMemory(mytree) function or magic I can use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不…忘初心 2024-11-13 07:23:15

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

Don't know it this is what you want but gcc has -Wmaybe-uninitialized and -Wuninitialized. There may be more on the warning options page.

空心空情空意 2024-11-13 07:23:15

使用 valgrind (在 Linux 上)

./valgrind myprogram

当我的程序使用调试信息(gcc -g)编译时特别容易,但不是必需的。 Valgrind 将通知未初始化的内存正在使用的位置以及从何处分配。如果它有调试信息,valgrind 将准确报告发生在哪个 file:linenumber 上。 (它甚至可以动态附加一个调试器,以便您检查事物

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

这里结束了有用的答案


编辑因为不太清楚我发布以下内容的原因,从评论中可以清楚地看出,让我介绍一下这个答案的其余部分:

当开始在现有代码库中使用 valgrind 时,几乎不可避免地会得到“误报”,即报告(还不是真正的问题)。我提供了一个可能触发此类报告的示例,以及您通常如何修复这些问题。

我添加此内容只是为了提高人们对如何处理或识别(半)误报的认识。

另一种措辞方式(参考评论中 Matthieu 令人信服的推理)是即使是“并非真正致命的”Valgrind 警告也视为至关重要:修复它们,而不是忘记

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

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

 char clone[1024];
 memcpy(clone, buf, 1024);

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

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

确保buf中没有未初始化的“部分”(或者至少不在访问的区域中)

Use valgrind (on linux)

./valgrind myprogram

Especially easy when myprogram was compiled with debug info (gcc -g), but not required. Valgrind will notify where memory is being used that was uninitialzed, and where it was allocated from. If it has debug info, valgrind will report exactly at which file:linenumber things happened. (it can even attach a debugger on the fly for you to insepct things)

It will also detect access beyond allocation boundaries and access after freeing. This is incredibly useful.

Here endeth the useful answer


Edit because it wasn't exactly clear why I was posting the following, as became clear from the comment, let me introduce the remainder of this answer:

When starting to use valgrind with existing codebases, it is almost inevitable that you'll get 'false' positives, i.e. reports that aren't really problems (yet). I include one example of what might trigger such a report, and how you'd typically fix those.

I'm just including this to raise awareness of how to tackle or recognize (semi-)false positives.

Another way of wording it (with reference to Matthieu's convincing reasoning in the comments) is to treat even the 'not-actually-killing' Valgrind warnings as critical: get them fixed, not forgotten.

It is possible that valgrind will report uninitialized access when it is not really a problem. Like, e.g.

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

 char clone[1024];
 memcpy(clone, buf, 1024);

You should fix that by doing something smarter like

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

To make sure there are no uninitialzed 'parts' in buf (or at least not in the area accessed)

心房敞 2024-11-13 07:23:15

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

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; }
};

Use a self-initializing class to cover those annoying primitives.

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; }
};
就此别过 2024-11-13 07:23:15

为了响应评论中链接的代码,RAIIIA(资源获取是操作中的初始化(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 背道而驰。这样做是可以的,但是由于您遇到未初始化变量的问题,我建议删除默认构造函数。

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

In response to the code linked in the comment, 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;
};

Your default constructor left the values unitialized, and goes against RAII in its pure form. It's OK to do that, but as you're having problems with uninitialized variables, I would recomment removing default constructors.

EDIT: storing unknown pointers as class members without newing and deleteing them in the class constructor/destructor isn't really RAII, but I hope you do that somewhere.

迷荒 2024-11-13 07:23:15

我通过使用带有模板的解决方案来解决这个问题,就像属性一样。我使用了 C++ 中的类似特性的属性? 但还有其他示例其他事情,例如传递 get/setter。

基本上生成了大部分代码,因为我能够并且跟踪变量是否通过属性设置。最后我只是检查成员并断言告诉我是否设置了变量。当我“得到”时我也会断言以防万一。

I solved this by using a solution with templates to act like properties. I used Property like features in C++? but there are other examples for other things like passing in a get/setter.

Essentially generated most of this code bc i was able to and i kept track if a variable was set or not through the property. At the end i just check members and had asserts to tell me if i set a variable or not. I also assert when i 'get' just in case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文