2014-07-11 59 views
6

我有一個C++程序調用Flex/Bison生成的一些C例程。我無法訪問的malloc()返回地址

當我定位在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); 
} 

我跟蹤d回到malloc電話,並觀察到malloc本身正在返回地址0x000000005A818118。我也檢查了errno,但在撥打malloc後沒有設置。

我的問題是:爲什麼malloc給我一個我無法訪問的地址,我該如何讓它給我一個正確的地址?

注意:我只在Windows 8.1 64位中觀察到這種行爲。它與其他32位Windows版本以及Windows 7 32位版本一起傳遞。

彙編信息:我是一個64位Windows 8.1的機器上使用Visual Studio 2012

如果有幫助編寫本,這裏是反彙編代碼:

// 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 

謝謝!

+0

我重複這個段多次,'malloc'返回'00000000 --------'或'FFFFFFFF --------'分配空間的地址。 –

+0

最有可能的是,一些其他看似無關的代碼部分已經設法破壞堆(例如,通過溢出堆分配的緩衝區)。你正在看的部分代碼是一個無辜的受害者。 –

+0

您的程序正在遇到堆損壞情況。你可以參考這篇文章的帖子:http://stackoverflow.com/a/22074401/2724703 –

回答

3

真正的答案是:

當您編譯在Visual Studio彎曲產生的.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

+0

我只能想象你剛剛用這個答案爲我節省了多少時間。 – Rafal

2

在正常情況下malloc()會返回一個指向有效的,可訪問的內存或NULL的指針。所以,你的症狀表明malloc()的行爲是不確定的。我懷疑,在某個時間點之前,您的程序在其有效內存之外寫入,從而破壞了malloc()內部使用的數據結構。

使用運行時內存分析工具檢查您的進程應該可以幫助您找出問題的根源。 [見這個職位上的內存分析工具,建議適用於Windows:Is there a good Valgrind substitute for Windows?]

+0

謝謝,這是一個很好的建議。我會盡快研究它,只要我可以安裝Windows 8兼容泄漏檢測器......儘管我在這個應用程序的Linux版本上運行了Valgrind,但似乎沒有任何可疑的東西。在運行代碼的這部分時,我只丟失了4個字節(由於庫函數我無法更改...) –