C++ 64位体系结构-从函数返回时字符指针被截断 环境:

C++ 64位体系结构-从函数返回时字符指针被截断 环境:,c++,c,windows,64-bit,C++,C,Windows,64 Bit,Windows x64位,带5GB RAM。我的二进制文件是64位的,编译版本为“Microsoft(R)C/C++优化编译器版本14.00.50727.762 for x64” 环境设置: Microsoft建议设置下面的注册表项来测试64位应用程序,我已经在我的框中设置了相同的注册表项。如果我不设置下面的注册表,问题就不会发生,因为程序位于较低的地址。讨论中提到了相同的注册表项- 要强制分配从较高地址分配到较低地址,以便进行测试,请在调用VirtualAlloc时指定MEM_TOP_DOWN

Windows x64位,带5GB RAM。我的二进制文件是64位的,编译版本为“Microsoft(R)C/C++优化编译器版本14.00.50727.762 for x64”

环境设置: Microsoft建议设置下面的注册表项来测试64位应用程序,我已经在我的框中设置了相同的注册表项。如果我不设置下面的注册表,问题就不会发生,因为程序位于较低的地址。讨论中提到了相同的注册表项-

要强制分配从较高地址分配到较低地址,以便进行测试,请在调用VirtualAlloc时指定MEM_TOP_DOWN,或将以下注册表值设置为0x100000:

HKEY\U LOCAL\U MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference

示例代码: 分析:
malloc
返回存储在
temp
中的地址
0x000007fffe999b40
,但当指针返回到
main()
时,
str
仅获取下半部分-
0xFFFFFFFE999B40
,我无法访问该位置的数据。

您参考的注册表设置选择自上而下的内存分配。您声明此设置将“将程序置于高地址空间”。它不会那样做的。这将强制Windows内存管理器从地址空间的顶部分配内存

更重要的是,由于您在64位Windows下运行,我无法看到PAE在何处发挥作用。这将在32位平台上使用

我猜您正在编译一个32位的应用程序,因此不可避免地您的指针是32位宽的。但由于缺乏信息,这只是一个猜测


简而言之,您的问题无法回答,因为您还没有告诉我们您在做什么。

我必须询问您是否使用了正确的编译器设置并针对正确的C运行时库进行了链接。

关于样式的两点,这有助于诊断此类问题。当您使用malloc时,我假设它被编译为一个C程序。在这种情况下,不要在不必要时进行类型转换。过多的类型转换可能会抑制告诉您没有正确声明函数的警告。如果没有原型并且函数定义在另一个模块中,那么调用
str=(char*)alloc_str()
将取消该函数在未声明的情况下使用的警告,并将使用默认的C声明,即所有参数和返回值将被视为
int
。 与
malloc
相同,如果您忘记了正确的include,您的类型转换将抑制警告,编译器将假定函数返回
int
。这可能已经是截断的原因。 另一点,在C语言中,一个空参数列表是用
(void)
声明的,而不是
()
,它有另一种含义(未指定的参数)。
这是C和C++的2个不同点。

< P >戴维,谢谢你的时间和建议。示例程序无法运行,因为我的C文件中没有包含
stdlib.h
,因此malloc返回的指针是32位的。我面临的问题是生产代码与示例代码有点不同

三体,你的解释绝对正确。我也面临同样的问题

在我的生产C文件中,我面临的问题如下

a.c

call_test1()
{
 char* temp;
 temp = (char *)test1();
}
include stdlib.h
char* test1()
{
 char *str;
 test = (char *)malloc(60);
 /* copy some data to test*/
 return str;
}
char * test1();
call_test1()
{
 char* temp;
 temp = test1();
}
include stdlib.h
char* test1()
{
 char *str;
 test = (char *)malloc(60);
 /* copy some data to test*/
 return str;
}
b.c

call_test1()
{
 char* temp;
 temp = (char *)test1();
}
include stdlib.h
char* test1()
{
 char *str;
 test = (char *)malloc(60);
 /* copy some data to test*/
 return str;
}
char * test1();
call_test1()
{
 char* temp;
 temp = test1();
}
include stdlib.h
char* test1()
{
 char *str;
 test = (char *)malloc(60);
 /* copy some data to test*/
 return str;
}
test1()
返回
str
时,指针包含64位地址(我使用“r rx”分析了windbg中的rx注册表(存储函数返回值),但当它被分配给
temp
时,它被截断为32位地址)

这个问题是由于

  • 在a.c文件中不包括
    test1()
    的签名
  • 将返回值类型转换为char*
  • 修正源

    a.c

    call_test1()
    {
     char* temp;
     temp = (char *)test1();
    }
    
    include stdlib.h
    char* test1()
    {
     char *str;
     test = (char *)malloc(60);
     /* copy some data to test*/
     return str;
    }
    
    char * test1();
    call_test1()
    {
     char* temp;
     temp = test1();
    }
    
    include stdlib.h
    char* test1()
    {
     char *str;
     test = (char *)malloc(60);
     /* copy some data to test*/
     return str;
    }
    
    b.c

    call_test1()
    {
     char* temp;
     temp = (char *)test1();
    }
    
    include stdlib.h
    char* test1()
    {
     char *str;
     test = (char *)malloc(60);
     /* copy some data to test*/
     return str;
    }
    
    char * test1();
    call_test1()
    {
     char* temp;
     temp = test1();
    }
    
    include stdlib.h
    char* test1()
    {
     char *str;
     test = (char *)malloc(60);
     /* copy some data to test*/
     return str;
    }
    
    我通过反复试验得到了解决方案,但三体素解释了原因

    64位注释
  • 使用%p而不是%lx在64位环境中打印指针地址
  • 包括函数签名并尽量避免类型转换指针
  • 在窗户上, 如果将C/C++代码重新编译为64位EXE或DLL,则必须使用AllocationPreference注册表值集对其进行测试
  • 要强制分配从较高地址分配到较低地址,以便进行测试,请在调用
    VirtualAlloc
    时指定
    MEM\u TOP\u DOWN
    ,或将以下注册表值设置为
    0x100000

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference
    

    我想你需要说出你实际上在做什么。你提到PAE。你能详细说明一下吗?你函数的返回类型是什么?返回值分配给哪一个变量?您可能会遇到这样的情况:指针中间存储的是某个32位类型的存储。这样的转换会剪切其他32位。请粘贴整个函数。如果它太大,那么把它简化成一个合理的复制。你所说的“被截断”是什么意思?你的程序的
    sizeof(char*)
    是什么?