【问题标题】:Why this function called in the heap can't call cout?为什么堆中调用的这个函数不能调用cout?
【发布时间】:2012-05-22 04:24:54
【问题描述】:

我试图调用在堆中分配的函数。经过一些失败的尝试后,我尝试了此网站中的代码:

http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/85d5da8c-edef-44b0-b42e-deb5f3eb2524

代码完美无缺。它编译、运行、给出正确/预期的结果,并且没有问题地完成。

但是,如果我尝试添加类似 std::cout

我想知道为什么会发生这种情况,以及如何解决这个问题。意识到我这样做的唯一目的是学习,我没有兴趣将其应用到实际使用中。

如果我堆函数调用一个使用 std::cout 打印数据的函数,那么该代码也不起作用。

【问题讨论】:

  • 我不会尝试这个,龙可能会飞出你的鼻子。
  • 我不怕。
  • Aa 我说,我不打算在现实生活中使用它。我永远不会做这样的事情。我只是想了解新事物,更好地了解某些事物的工作原理。

标签: c++ visual-c++ memory-management heap-memory


【解决方案1】:

您的问题在于,当您将cout 代码添加到函数时,您实际上添加了一些函数调用。 Microsoft C/C++ 编译器使用一些基本的堆栈帧检查来检测运行时的问题。这些检查是通过在每个函数调用后调用__RTC_CheckEsp 函数来执行的。对__RTC_CheckEsp 的调用使用E8 操作码,这意味着相对寻址。当示例函数被移动到堆中时,对__RTC_CheckEsp 的调用会发生错误,因为它会跳转到错误的位置。

禁用运行时堆栈帧检查(在 Visual Studio 2010 中):项目选项 -> 配置属性 -> C/C++ -> 代码生成 -> 基本运行时检查 -> 将其设置为未初始化变量

重新编译。跑步。尽情享受吧!

【讨论】:

  • 另一种选择是将此函数编译为与位置无关的代码 (PIC)。不幸的是,x86/x64 Win32 ABI 不支持 PIC,因此 MSVC 和 GCC/Win32 都不支持 x86/x64 Windows 上的 PIC 代码(但两者都在 Itanium 上支持)。
  • 如果您尝试打印cout << "asdasd" 之类的字符串,它将不起作用:std::operator<<<std::char_traits<char> > 由相对调用调用。我认为所有模板方法都是如此,因为它们不是库的一部分,而是在编译时创建的,因此被相关调用调用。
【解决方案2】:

在您引用的文章中,它指出:

只使用局部变量,不要使用全局变量、静态变量和常量字符串变量。

但是std::cout 是一个全局变量。而且我认为字符串文字可能会被归类为“常量字符串变量”,尽管文章术语有些不精确。

正如其他人所说,这段代码的行为是未定义的,所以究竟发生了什么是特定于实现的。不同的编译器可能会有不同的行为。

【讨论】:

  • 有没有办法调用堆中函数的静态/全局/常量值来处理此类数据?
  • 也许将全局变量等作为参数传递给函数。但你真正的问题是什么?
  • 我没有真正的问题,我只是想了解新的东西。
  • 查看调试器,单步执行 asm,了解如何引用全局变量。
【解决方案3】:

你在这里依赖未定义的行为,并期望它做一些理智的事情。

如果您想知道您的特定平台上发生了什么“错误”,我建议使用调试器来单步调试机器代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多