malloc()返回我无法访问的地址

时间:2014-07-11 18:45:57

标签: c++ c visual-studio-2010 malloc flex-lexer

我有一个C ++程序,它调用由Flex / Bison生成的一些C例程。

当我以Windows 8.1 64位平台为目标时,我在运行时遇到以下异常:

Unhandled exception at 0x0007FFFA70F2C39 (libapp.dll) in application.exe: 0xC0000005: 
Access violation writing location 0x000000005A818118.

我将此异常跟踪到以下代码:

YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
{
   YY_BUFFER_STATE b;
   b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
   if ( ! b )
      YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
   b->yy_buf_size = size; // This access is what throws the exception
}

作为参考,在代码的其他地方(也由Flex / Bison生成),我们有:

typedef struct yy_buffer_state *YY_BUFFER_STATE;
struct yy_buffer_state
{
   FILE *yy_input_file;
   char *yy_ch_buf;
   char *yy_buf_pos;
   yy_size_t yy_buf_size;
   // ... other fields omitted,
   // total struct size is 56 bytes
}

static void *yy_flex_alloc( yy_size_t size )
{
   return (void *) malloc( size );
}

我追溯到malloc电话,发现malloc本身正在返回地址0x000000005A818118。我还检查了errno,但在调用malloc之后未设置。

我的问题是:为什么malloc会给我一个我无法访问的地址,如何让它给我一个正确的地址?

注意:我只在Windows 8.1 64位中观察到此行为。它通过其他32位Windows变体,以及Windows 7 32位。

编译信息:我正在使用Visual Studio 2012在64位Windows 8.1计算机上进行编译。

如果有帮助,这里是反汇编的代码:

// b = (YY_BUFFER_STATE) yy_flex_alloc( ... )
0007FFFA75E2C12  call   yy_flex_alloc (07FFFA75E3070h)
0007FFFA75E2C17  mov    qword ptr [b],rax
// if ( ! b ) YY_FATAL_ERROR( ... )
0007FFFA75E2C1C  cmp    qword ptr [b],0
0007FFFA75E2C22  jne    yy_create_buffer+30h (07FFFA75E2C30h)
0007FFFA75E2C24  lea    rcx,[yy_chk+58h (07FFFA7646A28h)]
0007FFFA75E2C2B  call   yy_fatal_error (07FFFA75E3770h)
// b->yy_buf_size = size
0007FFFA75E2C30  mov    rax,qword ptr [b]
0007FFFA75E2C35  mov    ecx,dword ptr [size]
0007FFFA75E2C39  mov    dword ptr [rax+18h],ecx

谢谢!

2 个答案:

答案 0 :(得分:6)

真正的答案是:

在Visual Studio中编译flex生成的.c源时,它不包含stdlib.h(其中 malloc 定义为返回 void * )和Visual Studio采用自己的定义,其中 malloc 返回 int 。 (我认为它具有某种兼容性)

Visual studio打印:

  

'警告C4013:' malloc'不确定的;假设extern返回int'   sizeof(int)== 4,但x64系统上指针中的值通常超过4个字节

所以你的指针只能缩减到4个字节。

似乎此问题仅出现在x64个文件中.c位视觉工作室中。

因此,解决方案将是 - 只需自己包含 stdlib.h ,或定义一些宏,这将导致flex生成的源包括stdlib.h

答案 1 :(得分:2)

在正常情况下,malloc()将返回指向有效的可访问内存的指针,否则为NULL。因此,您的症状表明malloc()的行为方式不明确。我怀疑,在某些时候,你的程序在其有效内存之外编写,从而破坏了malloc()内部使用的数据结构。

使用运行时内存分析工具检查您的流程应该可以帮助您确定问题的根源。 [有关Windows内存分析工具的建议,请参阅此帖子:Is there a good Valgrind substitute for Windows?]