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

visual studio 2013 truncates returned pointer value in x64

我尝试为 x64 编译 wingraphviz(这是一个旧的、无人维护的项目),并且 运行 变成了一个非常 st运行ge 的问题:

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

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

(原代码是在函数调用里面调用的,为了理解我提取出来了)

getDefaultFont函数非常简单,return是一个基于当前字符集的字符串乱码:

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

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

            default:
            return DEFAULT_FONTNAME;
            break;
    }
}

with DEFAULT_FONTNAME & others defined in a header file:

#define     DEFAULT_FONTNAME    "Times New Roman"

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

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

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

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

call 指令之后,RAX 包含正确的值,一个指向 .data 的指针:RAX = 000007FEDA0C9A20 但是下一条指令 cqde "Convert dword (eax) to qword (rax)." 破坏了 4 个高位字节,现在 RAX = FFFFFFFFDA0C9A20。然后第三个将截断的值存储在堆栈上。

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

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

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

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

尤其是:

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

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

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

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