2017-06-26 19 views
5

我有以下非常簡單的C程序(test.c)「無效寫」:意外的valgrind當fstack檢查用於

int f(int i) 
{ 
    return i; 
} 

int main(int argC, char* argV[]) 
{ 
    int x = f(12); 
    return 1; 
} 

我已經做了一些試驗用的valgrind,在兩次與-fstack-check編譯器標誌打不同的系統。

測試在Debian 8.6與gcc 4.9.2和valgrind 3.10.0。

沒有-fstack-check

$ gcc test.c -o test 
$ valgrind ./test 
==103703== Memcheck, a memory error detector 
==103703== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==103703== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==103703== Command: ./test 
==103703== 
==103703== 
==103703== HEAP SUMMARY: 
==103703==  in use at exit: 0 bytes in 0 blocks 
==103703== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 
==103703== 
==103703== All heap blocks were freed -- no leaks are possible 
==103703== 
==103703== For counts of detected and suppressed errors, rerun with: -v 
==103703== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1) 

隨着-fstack-check

$ gcc -fstack-check test.c -o test 
$ valgrind ./test 
==103726== Memcheck, a memory error detector 
==103726== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==103726== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info 
==103726== Command: ./test 
==103726== 
==103726== 
==103726== HEAP SUMMARY: 
==103726==  in use at exit: 0 bytes in 0 blocks 
==103726== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 
==103726== 
==103726== All heap blocks were freed -- no leaks are possible 
==103726== 
==103726== For counts of detected and suppressed errors, rerun with: -v 
==103726== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1) 

測試中的CentOS 6.6用gcc 4.4.7和3.8.1 Valgrind的完成:

沒有-fstack-check

$ gcc test.c -o test 
$ valgrind ./test 
==16390== Memcheck, a memory error detector 
==16390== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==16390== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==16390== Command: ./test 
==16390== 
==16390== 
==16390== HEAP SUMMARY: 
==16390==  in use at exit: 0 bytes in 0 blocks 
==16390== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 
==16390== 
==16390== All heap blocks were freed -- no leaks are possible 
==16390== 
==16390== For counts of detected and suppressed errors, rerun with: -v 
==16390== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6) 

隨着-fstack-check

$ gcc -fstack-check test.c -o test 
$ valgrind ./test 
==16441== Memcheck, a memory error detector 
==16441== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==16441== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==16441== Command: ./test 
==16441== 
==16441== Invalid write of size 8 
==16441== at 0x400497: main (in /home/fermin/valgrindtest/test) 
==16441== Address 0x7feffd058 is not stack'd, malloc'd or (recently) free'd 
==16441== 
==16441== 
==16441== Process terminating with default action of signal 11 (SIGSEGV) 
==16441== Access not within mapped region at address 0x7FEFFD058 
==16441== at 0x400497: main (in /home/fermin/valgrindtest/test) 
==16441== If you believe this happened as a result of a stack 
==16441== overflow in your program's main thread (unlikely but 
==16441== possible), you can try to increase the size of the 
==16441== main thread stack using the --main-stacksize= flag. 
==16441== The main thread stack size used in this run was 10485760. 
==16441== 
==16441== HEAP SUMMARY: 
==16441==  in use at exit: 0 bytes in 0 blocks 
==16441== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 
==16441== 
==16441== All heap blocks were freed -- no leaks are possible 
==16441== 
==16441== For counts of detected and suppressed errors, rerun with: -v 
==16441== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6) 

在這種情況下,此外,該程序與段錯誤結束。

綜上所述,而Debian的一切似乎是確定與-fstack-check,在CentOS的我收到一個「無效寫」錯誤,我無法解釋給我的程序代碼。

閱讀有關the -fstack-check flag也許是錯誤跟蹤是由於堆棧檢查機制是分配在堆空間8個字節的x變量,但Valgrind的(由於某些原因)不能獲得意識到這一點,所以它標誌着它作爲無效寫入。也許這是valgrind 3.8.1中的一個限制,已經在3.10.0中解決了(考慮到在Debian的設置中,使用3.10.0,我沒有得到這個跟蹤)?

另外,我似乎在valgring FAQ「和-fstack-check可以使堆棧跟蹤雪上加霜」但他們沒有提供關於原因,所以我不知道,如果問題是相關的信息太多了..

任何幫助或暗示,這有助於解釋這一點,高度讚賞。

編輯:作爲一項評論所說,我包括CentOS的6.x的情況下,dissasembled代碼,與-g3編譯和使用objdump --source test。我在這裏包括與main()和f()函數相對應的部分,但是可以找到完整的轉儲here

二進制編譯-fstack-check

0000000000400474 <f>: 
int f(int i) 
{ 
    400474: 55      push %rbp 
    400475: 48 89 e5    mov %rsp,%rbp 
    400478: 89 7d fc    mov %edi,-0x4(%rbp) 
    return i; 
    40047b: 8b 45 fc    mov -0x4(%rbp),%eax 
} 
    40047e: c9      leaveq 
    40047f: c3      retq 

0000000000400480 <main>: 

int main(int argC, char* argV[]) 
{ 
    400480: 55      push %rbp 
    400481: 48 89 e5    mov %rsp,%rbp 
    400484: 48 83 ec 20    sub $0x20,%rsp 
    400488: 89 7d ec    mov %edi,-0x14(%rbp) 
    40048b: 48 89 75 e0    mov %rsi,-0x20(%rbp) 
    int x = f(12); 
    return 0; 
    40048f: 48 8d 84 24 08 d0 ff lea -0x2ff8(%rsp),%rax 
    400496: ff 
    400497: 48 c7 00 00 00 00 00 movq $0x0,(%rax) 
    return i; 
} 

int main(int argC, char* argV[]) 
{ 
    int x = f(12); 
    40049e: bf 0c 00 00 00   mov $0xc,%edi 
    4004a3: e8 cc ff ff ff   callq 400474 <f> 
    4004a8: 89 45 fc    mov %eax,-0x4(%rbp) 
    return 0; 
    4004ab: b8 00 00 00 00   mov $0x0,%eax 
} 
    4004b0: c9      leaveq 
    4004b1: c3      retq 

二進制編譯時沒有-fstack-check

0000000000400474 <f>: 
int f(int i) 
{ 
    400474: 55      push %rbp 
    400475: 48 89 e5    mov %rsp,%rbp 
    400478: 89 7d fc    mov %edi,-0x4(%rbp) 
    return i; 
    40047b: 8b 45 fc    mov -0x4(%rbp),%eax 
} 
    40047e: c9      leaveq 
    40047f: c3      retq 

0000000000400480 <main>: 

int main(int argC, char* argV[]) 
{ 
    400480: 55      push %rbp 
    400481: 48 89 e5    mov %rsp,%rbp 
    400484: 48 83 ec 20    sub $0x20,%rsp 
    400488: 89 7d ec    mov %edi,-0x14(%rbp) 
    40048b: 48 89 75 e0    mov %rsi,-0x20(%rbp) 
    int x = f(12); 
    40048f: bf 0c 00 00 00   mov $0xc,%edi 
    400494: e8 db ff ff ff   callq 400474 <f> 
    400499: 89 45 fc    mov %eax,-0x4(%rbp) 
    return 0; 
    40049c: b8 00 00 00 00   mov $0x0,%eax 
} 
    4004a1: c9      leaveq 
    4004a2: c3      retq 

EDIT2:我已經在CentOS的當下(3.13.0)與最新的valgrind測試版6.8,我也遇到同樣的問題。

+0

如果您更改main的返回值,即「1」以外的任何值,您是否檢查過該行爲? – cse

+0

我也嘗試過'return 0'和'return 2',結果在CentOS 6.6中使用'-fstack-check'是相同的(即「無效寫入」)。無論如何感謝您的建議! – fgalan

+0

你可以粘貼拆散的代碼嗎? – alinsoar

回答

2

我在我的CentOS 6.6系統安裝GCC 4.7.2(使用this procedure),並重新做了測試與-fstack-check編譯:現在沒有顯示「無效寫」錯誤

$ /opt/centos/devtoolset-1.1/root/usr/bin/gcc --version 
gcc (GCC) 4.7.2 20121015 (Red Hat 4.7.2-5) 
Copyright (C) 2012 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ /opt/centos/devtoolset-1.1/root/usr/bin/gcc -fstack-check test.c -o test 
$ valgrind ./test 
==19374== Memcheck, a memory error detector 
==19374== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==19374== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==19374== Command: ./test 
==19374== 
==19374== 
==19374== HEAP SUMMARY: 
==19374==  in use at exit: 0 bytes in 0 blocks 
==19374== total heap usage: 0 allocs, 0 frees, 0 bytes allocated 
==19374== 
==19374== All heap blocks were freed -- no leaks are possible 
==19374== 
==19374== For counts of detected and suppressed errors, rerun with: -v 
==19374== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6) 

注意。因此,這似乎是gcc編譯器中的一個問題,在4.4.7和4.7.2之間修正了一些bug,如@ n.m。在評論中提出。