C++ 在运行时确定参数的性质
我有一个函数C++ 在运行时确定参数的性质,c++,memory,new-operator,C++,Memory,New Operator,我有一个函数 void fname(char* Ptr) { ... } 我想知道在这个函数中,这个指针Ptr是使用newchar[]保存动态分配内存的地址,还是调用函数中本地分配内存的地址。有什么办法可以确定吗?我认为在这里没有帮助 简单的回答是:不,你不能。您无法知道Ptr是否是指向单个char的指针、静态分配数组的开头、指向单个动态分配char的指针或数组的开头 如果您真的想,您可以尝试这样的重载: template <std::size_t N> void fnam
void fname(char* Ptr)
{
...
}
我想知道在这个函数中,这个指针
Ptr
是使用newchar[]
保存动态分配内存的地址,还是调用函数中本地分配内存的地址。有什么办法可以确定吗?我认为
在这里没有帮助 简单的回答是:不,你不能。您无法知道Ptr
是否是指向单个char
的指针、静态分配数组的开头、指向单个动态分配char
的指针或数组的开头
如果您真的想,您可以尝试这样的重载:
template <std::size_t N>
void fname(char Ptr[N])
{
// ...
}
模板
void fname(char Ptr[N])
{
// ...
}
当传递一个静态分配的数组时,它将匹配,而当处理动态分配的内存或指向单个char
的指针时,将选择第一个版本
(但请注意,在存在模板的情况下,函数重载规则有点复杂——特别是,如果匹配,则首选非模板函数。因此,如果采用这种方法,可能需要使原始函数采用“伪”模板参数。)一种方法是让您自己的
操作员拥有新的
功能,并跟踪分配的所有内容,这样您就可以询问分配库给定的地址是否是它分配的地址。然后,自定义分配器只调用标准分配器来实际执行分配
另一种方法(凌乱且细节高度依赖操作系统)可能是检查虚拟内存中的进程布局,从而确定哪些地址指的是内存的哪些区域
您可以通过实际管理自己的内存池来结合这些想法。因此,如果您获得一大块具有已知地址边界的系统内存,并将其用于所有新
'd内存,您只需检查给定范围内的地址即可回答您的问题
然而:如果这个问题是这样做的唯一目的,那么这些想法中的任何一个都是大量的工作,是不合适的
话虽如此,如果你真的想实现一些东西,你需要仔细研究所有可能生成地址的方法
例如(我肯定错过了一些):
- 堆叠
- 从纽约回来
- 里面有一件从新买回来的东西
- 从新的返回,但已删除(希望不是,但这就是我们需要诊断的原因)
- 静态分配
- 静态恒定存储器
- 命令行参数/环境
- 代码地址
char* firstStack = 0;
bool isOnStack(const void* p)
{
char* check =(char*)p;
char * here = (char*)✓
int a = firstStack - check;
int b = check - here;
return (a*b > 0);
}
void g(const char* p)
{
bool onStack = isOnStack(p);
std::cout << p << (onStack ? "" : " not" ) << " on stack " << std::endl;
}
void f()
{
char stuff[1024] = "Hello";
g(stuff);
}
void h()
{
char* nonsense = new char[1024];
strcpy(nonsense, "World");
g(nonsense);
delete [] nonsense;
}
int main()
{
int var = 0;
firstStack = (char*)&var;
f();
h();
}
char*firstStack=0;
bool isOnStack(const void*p)
{
字符*检查=(字符*)p;
char*here=(char*)&check;
int a=第一堆栈-检查;
int b=检查-此处;
返回(a*b>0);
}
空g(常量字符*p)
{
bool-onStack=isOnStack(p);
std::cout在vc++中有一个断言_CrtIsMemoryBlock(),可用于检查指针是否从堆中分配。这仅在使用调试堆时有效,但如果您只是想添加一些“仅调试”断言,则可以使用。过去在Windows下,此方法对我很有效
然而,对于Linux,我不知道有这样的等价物
或者,您可以使用内联汇编程序块来尝试确定它是否是堆栈地址。这将取决于硬件,因为它不仅严重依赖于处理器类型,还严重依赖于所使用的内存模型(平面地址模型与分段等)。最好避免这种方法。我看到的一种可能性是通过使用delete[]
运算符。如果指针不包含动态分配内存的地址,那么delete[]Ptr
应该会产生运行时错误。它有什么好处吗?@Prakash No,delete[]
不会引发异常(在C++11中,它被显式地标记为noexcept
)。试图在静态分配的东西上使用它,充其量是未定义的行为,可能只是崩溃。