我正在将一个类型从C风格的结构转换为C ++风格的结构;我正在添加一个强制类型需要构造函数的成员,因此我必须从malloc
和free
切换到new
和delete
。通过查找sizeof(TYPE)
,我可以找到分配类型的所有地方(由于此代码库的约定)。
有什么方法可以找到将该类型的指针传递给free
的所有实例?我意识到,因为free
的论证是void*
,这不是我在任何地方找到的类型的保证。
例如,我可以以某种方式重载free
,以便在调用free(TYPE*)
的任何地方都会出现编译错误,而不是在其他地方吗?
答案 0 :(得分:6)
我可以以某种方式超载吗
你当然可以试一试。例如:
#include <cstdlib>
#include <iterator>
namespace my {
class TYPE { };
template <typename T>
void free(T *ptr) { std::iterator_traits<T>::attempt_to_free_TYPE; }
}
using std::malloc;
using std::free;
using my::TYPE;
int main() {
TYPE *ptr = (TYPE *) malloc(sizeof(TYPE));
free(ptr);
}
感谢ADL,对free
的调用是my::free
,因此代码无法编译。显然这不会捕获free((void*)ptr);
,因为使用free
以外的参数调用my::TYPE*
不会受到影响。
正如我所写,不需要在free
内部my
或using namespace my;
的代码中调用std::free
。因此,您可能希望使用新发明的命名空间。或者写一个不那么全面的模板,我即兴创作了一个。
它也无法捕获对std::free
的完全限定的呼叫。重载template <typename T>
struct allowed_to_free {
enum { value };
};
template <>
struct allowed_to_free<TYPE> {};
namespace std {
template <typename T>
void free(T *ptr) {
allowed_to_free<T>::value;
free((void*)ptr);
};
}
(或命名空间std中的任何内容)是未定义的行为,但如果有必要,您可能只是为了查找调用站点而逃脱它。像这样:
{{1}}
答案 1 :(得分:0)
使用valgrind:如果您愿意在运行时进行检查,请考虑使用valgrind来执行此类任务。
Valgrind会在您错误地free
分配new()
分配的对象时告诉您。
由于OP不在Linux中而在VS中,我猜有类似于valgrind的工具。
另一个选择是使用静态分析器,例如覆盖率或clang-analyze。
答案 2 :(得分:0)
您无法直接执行此操作...但是,您可以使用技巧来查找使用此类(错误初始化的)实例的所有位置。只需将前结构的所有成员 - 现在的类 - 私有。无论何时使用这些字段/成员,编译器都会引发错误。这将为您提供进一步分析代码并消除所有malloc /免费调用的起点。