Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么覆盖的“operator new”不是';你没打电话吗?_C++_Visual Studio 2005_Operator Overloading_New Operator - Fatal编程技术网

C++ 为什么覆盖的“operator new”不是';你没打电话吗?

C++ 为什么覆盖的“operator new”不是';你没打电话吗?,c++,visual-studio-2005,operator-overloading,new-operator,C++,Visual Studio 2005,Operator Overloading,New Operator,我在VS2005中运行以下代码: #include <iostream> #include <string> #include <new> #include <stdlib.h> int flag = 0; void* my_alloc(std::size_t size) { flag = 1; return malloc(size); } void* operator new(std::size_t size) { retu

我在VS2005中运行以下代码:

#include <iostream>
#include <string>
#include <new>
#include <stdlib.h>

int flag = 0;

void* my_alloc(std::size_t size)
{
    flag = 1;
    return malloc(size);
}

void* operator new(std::size_t size) { return my_alloc(size); }
void operator delete(void* ptr) { free(ptr); }
void* operator new[](std::size_t size) { return my_alloc(size); }
void operator delete[](void* ptr) { free(ptr); }

int main()
{
    std::string str;
    std::getline(std::cin, str);
    std::cout << str;
    return flag;
}
在调试编译中,进程返回1,在发布配置中,进程返回0,这意味着不调用
new
操作符!我可以通过设置断点、写入输出/调试输出等来验证这一点


这是为什么?这是一种标准的一致性行为吗?

调用cout确实应该一步一步地调试代码。您是否尝试在发布配置中设置/Od以禁用优化?我想知道这是否会改变行为。

您有无限递归

相反,你喜欢什么

#include <iostream>
#include <string>
#include <new>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

void* my_alloc( char const* str, std::size_t size )
{
    fprintf( stderr, "%s %lu\n", str, (unsigned long)size );
    return malloc( size ); // I don't care for errors here
}

void* operator new( std::size_t size )      { return my_alloc( "new", size ); }
void operator delete( void* ptr )           { free(ptr); }
void* operator new[]( std::size_t size )    { return my_alloc( "new[]", size ); }
void operator delete[]( void* ptr )         { free( ptr ); }

int main()
{
    std::string str;
    std::cout << "? ";
    std::getline(std::cin, str);
    std::cout << str;
}
#包括
#包括
#包括
#包括
#包括
#包括
void*my_alloc(字符常量*str,std::size\u t size)
{
fprintf(stderr,“%s%lu\n”,str,(无符号长)大小);
return malloc(size);//我不在乎这里的错误
}
void*运算符new(std::size_t size){返回我的alloc(“new”,size);}
void操作符delete(void*ptr){free(ptr);}
void*运算符new[](std::size_t size){返回my_alloc(“new[]”,size);}
void操作符delete[](void*ptr){free(ptr);}
int main()
{
std::字符串str;

std::cout经过一些研究,@bart jan在他们的另一个答案(现已删除)中所写的事实上是正确的

很容易看出,在发布中根本没有调用mine operator,而是调用了CRT版本。(不,对于所有在黑暗中拍摄的人来说,这里没有递归。)问题是“为什么”

以上内容是根据动态链接的CRT(默认设置)编译的。Microsoft在CRT DLL中提供了
std::string
(以及许多其他标准模板)的实例化。查看VS2005附带的Dinkumware标头:

#if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE)

template class _CRTIMP2_PURE allocator<char>;
// ...
template class _CRTIMP2_PURE basic_string<char, char_traits<char>,
    allocator<char> >;
#如果已定义(_DLL_CPPLIB)和&!已定义(_M_CEE_PURE)
模板类_CRTIMP2_纯分配器;
// ...
模板类\u CRTIMP2\u纯基本\u字符串;
其中
\u CRTIMP2\u PURE
扩展为
\u declspec(dllimport)
。这意味着在发行版中,链接器将
std::string
链接到构建CRT时实例化的版本,该版本使用
new
的默认实现

不清楚为什么调试中不会发生这种情况。正如@Violet Giraffe正确猜测的那样,它一定受到某些开关的影响。但是,我认为是链接器开关,而不是编译器开关。我无法确切确定哪个开关起作用



其他答案忽略的剩余问题是“它是标准的吗”?在VS2010中尝试代码时,它确实调用了我的
操作符new
,无论我编译的是什么配置!查看VS2010附带的标题,它显示Dinkumware删除了
\u declspec(dllimport)
用于上述实例化。因此,我认为旧的行为确实是一个编译器错误,而不是标准行为。

您是否尝试过调试和单步执行代码,而不是依赖于输出?@Kolky:是的。例如,我在
操作符new
中设置了一个全局标志,并从主解决方案返回它,但根本没有输出。有一个GCC中有趣的bug@KerrekSB:有趣。是的,我知道它与vector一起工作。它确实是一个bug。请看我的答案。std::ostream@Violet:我没有。
const char*
不是一个
std::string
@bert jan:首先,我认为它不能符合标准。其次,即使没有任何输出,结果也是可复制的。如果你不稳定的话std::string()或use std::cout可能std::string关联的分配器决定不使用new()在本例的发行版中,这是一个遥远的猜测。它没有改变任何东西。与上面相同。@ybungalobill:好的,链接到调试运行时如何?尝试/MDd而不是/MD。此外,您现在可以尝试单步进入代码,查看哪个函数拦截控件。可能,有一些宏,它仅在发行版中定义?debug l没有优化的版本中的库:相同的结果。@ybungalobill:当进入
new
时,您会看到什么?嗯,我的新版本只是在发布时没有被编译。+1表示正确的方向。相同的结果。没有递归的版本(我也没有递归)请参见上面的编辑我用Visual C++ 10检查了它,除了你自己的原始bug之外,你还很可能碰到编译器错误。但是我认为这是不太可能的;最有可能是PEBCAK。请向我解释在第二代码片段中你看到的递归。在第一个剪辑中,我看不到/观察到递归,BTW.(可能)无限递归是在你的原始代码中,而不是第二个片段。第二个片段认为你最可能做的是错误的事情。比如运行错误的exe,不管怎样。第二个代码的问题没有用VisualC++ +10来复制。我将在用VS2010进入计算机时检查它。听起来好像是SOR。链接器/库错误的t,不允许有条件地替换函数的默认版本。GCC称此为“弱引用”;MSVC必须有一个类似的概念。@KerrekSB:不完全是。你不能在DLL的上下文中这样做。包含std::string实现的DLL已经与一些
新的
实现相链接,你以后在操作系统加载时不能重新绑定它。
#if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE)

template class _CRTIMP2_PURE allocator<char>;
// ...
template class _CRTIMP2_PURE basic_string<char, char_traits<char>,
    allocator<char> >;