我的意思是C和C ++。这个项目在C中使用了一个lib,它在C ++中调用我的函数。但是这些函数在extern“C”中,因为lib期望它。
无论如何,在这些功能中我做new Blah
。当调用特定函数(end_tree)时,我希望我的所有变量都被初始化。使用Visual Studios,GCC或任何其他编译器有一种方法可以检查吗?我只是注意到一些bool是真的,不应该......为什么,因为它没有被初始化。我可以使用某种_VS_CheckThisMemory(mytree)
函数或魔法吗?
答案 0 :(得分:3)
不知道这是你想要的,但gcc
有-Wmaybe-uninitialized
和-Wuninitialized
。 the warning options page上可能会有更多内容。
答案 1 :(得分:3)
使用valgrind(在linux上)
./valgrind myprogram
使用调试信息(gcc -g
)编译myprogram时非常容易,但不是必需的。 Valgrind将通知未使用的内存使用位置以及从中分配的位置。如果它有调试信息,valgrind将准确报告哪个文件:发生了事情。 (它甚至可以动态附加一个调试器,让你可以看到事情)
它还将检测超出分配边界的访问权限以及释放后的访问权限。这非常有用。
这里有用的答案
编辑,因为我发布以下信息的原因并不完全清楚,从评论中可以清楚地看到,让我介绍一下这个答案的其余部分:
当开始在现有代码库中使用valgrind时,几乎不可避免地会得到“假”肯定,即(尚未)真正出现问题的报告。我包含一个可能会触发此类报告的示例,以及通常修复这些报告的方式。
我只是将此包括在内,以提高对如何处理或识别(半)误报的认识。
另一种措辞方式(参考Matthieu在评论中令人信服的推理)是将“不实际杀人”的Valgrind警告视为关键:将它们固定,不要忘记。
可能 valgrind在没有真正问题时会报告未初始化的访问。比如,例如
char buf[1024];
strcpy(buf, "hello");
char clone[1024];
memcpy(clone, buf, 1024);
你应通过做更聪明的事情来解决这个问题,比如
memcpy(clone, buf, strlen(buf));
确保buf中没有未初始化的“部分”(或者至少不在访问的区域内)
答案 2 :(得分:2)
使用自我初始化类来覆盖那些恼人的原语。
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; }
};
答案 3 :(得分:1)
回应评论中链接的代码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;
};
您的默认构造函数将值保持为unitialized,并以纯粹的形式反对RAII。这样做是可以的,但是当你遇到未初始化变量的问题时,我会建议删除默认的构造函数。
编辑:将未知指针存储为没有new
的类成员,并且在类构造函数/析构函数中delete
不是真正的RAII,但我希望你能在某处做到这一点。
答案 4 :(得分:0)
我通过使用带有模板的解决方案来解决这个问题。我使用了Property like features in C++?,但还有其他一些例子,比如传入get / setter。
本质上生成了大部分代码bc我能够并且我跟踪是否通过属性设置了变量。最后我只是检查成员并断言告诉我是否设置变量。当我得到'以防万一时,我也断言。