c - visual studio 2013 截断 x64 中返回的指针值

标签 c visual-studio assembly compilation 64-bit

我尝试为 x64 编译 wingraphviz(这是一个旧的、无人维护的项目),遇到了一个非常奇怪的问题:

有一个对 getDefaultFont() 的调用,如下所示:

const char* def = getDefaultFont();
Deffontname = late_nnstring(g->proto->n,N_fontname,def);

(原始代码在函数调用中进行了调用,但我将其提取出来以供理解)

getDefaultFont 函数非常简单,返回一个基于当前字符集的字符串:

const char * getDefaultFont() {
    switch(DOT_CODEPAGE) {

            case CP_KOREAN:
            return CP_949_DEFAULTFONT;
            break;
[...]

            default:
            return DEFAULT_FONTNAME;
            break;
    }
}

使用 DEFAULT_FONTNAME 和头文件中定义的其他内容:

#define     DEFAULT_FONTNAME    "Times New Roman"

我将返回更改为 { const char* r = DEFAULT_FONTNAME;返回 r; 在调试时查看值:r 在返回指令中是正确的。

但是当调试器返回调用函数时,def 指向无效内存。

我在汇编模式下运行调试器,看到了:

    const char* def = getDefaultFont();
000007FEDA1244FE  call        getDefaultFont (07FEDA1291A0h)  
000007FEDA124503  cdqe  
000007FEDA124505  mov         qword ptr [def],rax  

call 指令之后,RAX 包含正确的值,一个指向 .data 的指针:RAX = 000007FEDA0C9A20 但下一条指令 cqde “将双字 (eax) 转换为四字 (rax)。”销毁 4 个更高的字节,现在 RAX = FFFFFFFFDA0C9A20。然后第三个将截断的值存储在堆栈上。

之后,late_nnstring() 尝试取消引用损坏的指针并崩溃...

你知道为什么VS插入这个cqde指令吗? 所有这些功能都在同一项目下的.c 文件中。

我已经实现了一个解决方法,使用 strdup() 返回低内存地址,但它不安全(也许堆可以在 4G 之后使用内存?)(还有一些我在测试时没有发现的其他情况使用库时会崩溃)

我在这里发布了文件:https://gitlab.com/data-public/wingraphviz

特别是:

最佳答案

您的链接需要一些我没有的帐户。

您可能没有包含声明该函数的 header ,或者弄乱了 header 顺序。 Here’s more info为什么 C 编译器插入 cdqe.

附言为什么您应该阅读并修复编译器警告的一个很好的例子。

更新:如果您有循环依赖问题并且不能只包含 utils.h,一个快速的解决方法是在 emit 中声明 const char * getDefaultFont();。 c 在调用该函数之前。

关于c - visual studio 2013 截断 x64 中返回的指针值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49455189/

相关文章:

c - 我应该如何开始编写设备驱动程序?

assembly - 如何在不使用 MUL 或 DIV 的情况下在 5 行中将数字乘以 42?

c - SHA256 摘要在数组初始值设定项和字符串之间有所不同

c - strlen如何计算c中的unicode

visual-studio - 在 Visual Studio 中自动逐步调试?

c# - 为什么 Visual Studio Debug模式无法正常工作(按下 F11 时执行 F5)?

c - 如何从上下文中手动递增指令指针?

c - FLOPS 什么是真正的 FLOP

c - 为什么 isnumber() 函数存在于某些 Unix 发行版中,而其他发行版中却没有?

visual-studio - 我可以使用 GhostDoc 将文档添加到整个类或代码文件吗?