2014-09-06 97 views
8

我一直在試圖理解爲什麼valgrind在使用ucontexts的這個小測試程序中抱怨「使用大小爲8的未初始化值」。 它基本上是一個程序,它創建「n_ucs」ucontexts並將它們切換爲「max_switch」次。valgrind錯誤和ucontext。爲什麼「使用未初始化的大小8」?

我明白「警告:客戶端切換堆棧?」 (這基本上是程序的一切),但我真的沒有任何意義,所有的「使用未初始化的大小8的值」

我想得到一些幫助理解,如果Valgrind錯誤是誤報或如果這個程序有根本錯誤。 (我在很大的程序中看到很多程序都使用相同的機制,但我已經將其精簡到最低限度,以便在此處發佈)。

任何幫助表示讚賞。

感謝,

傑克

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#include <ucontext.h> 

#define STACK_SIZE (8*1024) 

int n_ucs = 1; 
int max_switchs = 10; 
int n_switchs = 0; 
int tid = 0; 

ucontext_t *ucs; 
static ucontext_t engine_uc; 

static void func(int arg) 
{ 
    while (n_switchs < max_switchs) { 
     int c_tid = tid; 
     int n_tid = (tid + 1) % n_ucs; 
     n_switchs++; 
     tid = n_tid; 
     swapcontext(&ucs[c_tid], &ucs[n_tid]); 
    } 
} 

int main(int argc, char **argv) 
{ 
    if (argc > 1) 
     n_ucs = atoi(argv[1]); 
    if (argc > 2) 
     max_switchs = atoi(argv[2]); 

    ucs = malloc(sizeof(ucontext_t) * n_ucs); 
    int i; 
    for (i = 0; i < n_ucs; i++) { 
     /* Create initial ucontext_t, including stack */ 
     getcontext(&ucs[i]); 
     ucs[i].uc_stack.ss_sp = malloc(STACK_SIZE); 
     ucs[i].uc_stack.ss_size = STACK_SIZE; 
     ucs[i].uc_stack.ss_flags = 0; 
     ucs[i].uc_link = &engine_uc; 
     makecontext(&ucs[i], (void (*)())func, 1, i); 
    } 

    /* jump to the first uc */ 
    swapcontext(&engine_uc, &ucs[tid]); 

    /* destroy stacks */ 
    for (i = 0; i < n_ucs; i++) 
     free(ucs[i].uc_stack.ss_sp); 
    free(ucs); 
    return 0; 
} 

編譯GCC的main.c./a.out 2 2

GCC -v

運行

使用內置規格。 COLLECT_GCC = gcc COLLECT_LTO_WRAPPER =/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper 目標:x86_64-linux-gnu配置爲:../src/configure -v --with-pkgversion = 'Ubuntu 4.8.2-19ubuntu1'--with-bugurl = file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages = c,C++,java,go,d,fortran, objc,obj-C++ --prefix =/usr --program-suffix = -4.8 --enable-shared --enable-linker-build-id --libexecdir =/usr/lib --without-included-gettext - enable-threads = posix --with-gxx-include-dir =/usr/include/C++/4.8 --libdir =/usr/lib --enable -nls --with-sysroot =/--enable-clocale = gnu --enable-libstdcxx-debug --enable-libstdcxx-time = yes --enable-gnu-unique-object --disable -libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin - -enable-java-awt = gtk -enable-gtk-cairo -with-java-home =/usr/lib/jvm/java-1.5.0 -gcj-4.8-amd64/jre -enable -java-home --with-jvm-root-dir =/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --wit h-jvm-jar-dir =/usr/lib/jvm-exports/java-1.5.0 -gcj-4.8-amd64 -with-arch-directory = amd64 -with-ecj-jar =/usr/share/java/eclipse-ecj.jar --enable-objc -gc --enable-multiarch --disable-werror --with-arch-32 = i686 --with-abi = m64 --with-multilib-list = m32, m64,mx32 --with-tune = generic --enable-checking = release --build = x86_64-linux-gnu --host = x86_64-linux-gnu --target = x86_64-linux-gnu線程模型:posix gcc版本4.8.2(Ubuntu的4.8.2-19ubuntu1)

LDD --version

LDD(Ubuntu的EGLIBC 2.19-0ubuntu6.3)2.19版權所有(C) 2014自由軟件基金會這是自由軟件;請參閱 複製條件的來源。沒有保修;即使對於 適銷性或針對特定用途的適用性。作者Roland McGrath和Ulrich Drepper。

valgrind --track-origins=yes ./a.out 2 2 
==21949== Memcheck, a memory error detector 
==21949== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==21949== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 
==21949== Command: ./a.out 2 2 
==21949== 
==21949== Warning: client switching stacks? SP change: 0xffefffdd8 --> 0x51ff7b8 
==21949==   to suppress, use: --max-stackframe=68616717856 or greater 
==21949== Use of uninitialised value of size 8 
==21949== at 0x400738: func (main.c:25) 
==21949== by 0x4E58EC4: (below main) (libc-start.c:287) 
==21949== Uninitialised value was created by a stack allocation 
==21949== at 0x4E7E445: swapcontext (swapcontext.S:92) 
==21949== 
==21949== Conditional jump or move depends on uninitialised value(s) 
==21949== at 0x4E807A7: __start_context (__start_context.S:37) 
==21949== by 0x4E58EC4: (below main) (libc-start.c:287) 
==21949== Uninitialised value was created by a stack allocation 
==21949== at 0x4E7E445: swapcontext (swapcontext.S:92) 
==21949== 
==21949== Syscall param rt_sigprocmask(set) contains uninitialised byte(s) 
==21949== at 0x4E7E0EC: setcontext (setcontext.S:47) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== Uninitialised value was created by a stack allocation 
==21949== at 0x4E7E445: swapcontext (swapcontext.S:92) 
==21949== 
==21949== Use of uninitialised value of size 8 
==21949== at 0x4E7E0F5: setcontext (setcontext.S:54) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== Uninitialised value was created by a stack allocation 
==21949== at 0x4E7E445: swapcontext (swapcontext.S:92) 
==21949== 
==21949== Use of uninitialised value of size 8 
==21949== at 0x4E7E0FE: setcontext (setcontext.S:56) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== by 0x4E807AD: __start_context (__start_context.S:39) 
==21949== Uninitialised value was created by a stack allocation 
==21949== at 0x4E7E445: swapcontext (swapcontext.S:92) 
==21949== 
==21949== Warning: client switching stacks? SP change: 0x51ff7c0 --> 0xffefffde0 
==21949==   to suppress, use: --max-stackframe=68616717856 or greater 
==21949== 
==21949== HEAP SUMMARY: 
==21949==  in use at exit: 0 bytes in 0 blocks 
==21949== total heap usage: 3 allocs, 3 frees, 18,256 bytes allocated 
==21949== 
==21949== All heap blocks were freed -- no leaks are possible 
==21949== 
==21949== For counts of detected and suppressed errors, rerun with: -v 
==21949== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0) 
+1

假設你在64位架構上運行您的指針是64位(8個字節)。這還包括'&var' – clearlight 2017-01-31 17:15:16

+2

考慮使用['calloc()'](https://linux.die.net/man/3/calloc)分配內存,因爲與'malloc()'不同,'calloc() '不要忘記'calloc()'帶有第二個參數,參見[manpage](https://linux.die.net/man/3/calloc))或者使用'for ()'循環或使用'bzero()'或'memset()'來做到這一點。 – clearlight 2017-01-31 17:27:42

回答

1

我還是不完全明白爲什麼Valgrind是顯示這些初始化錯誤正是但我給它來解釋我的理解到現在我最好的拍攝;

在運行並通過valgrind分析程序並基於來自swapcontext(3)和getcontext(3)的手冊頁的信息時,我認爲它無法檢測到某些上下文交換(無法看到swapcontext的堆棧指針更改從TID 0至TID 1和TID 1 swapcontext回TID 0)

下面讀爲:誰的籌碼[呼叫號碼]:函數調用

所以,我覺得函數調用軌跡像這樣:

主:swapcontext(主,TID 0) - >

主要[TID 0的第一FUNC呼叫]:函數() - >

TID 0:swapcontext(TID 0,TID 1) - > { 堆棧=> 0 tiod}

TID 1:函數() - >

swapcontext(TID 1,TID 0) - > {堆棧=> tiod 1}

TID 0 [第二呼叫]:函數() - >

立即返回自n_switchs = 2 - >

彈出TID 0 [第二呼叫]:從TID 1的堆棧FUNC()堆棧幀 - >{根據的valgrind}

TID 0第一 未初始化接入[第二呼叫]:函數()完成 - >檢查uc_link;發現engine_uc (主要方面)設置有 - >

從這裏開始,事情就不清楚了我,但以下似乎是可能的跟蹤:

復位sigprocmask - >{2日未初始化的訪問} setcontext()秒 回到主上下文 - >{第三Uinitialized訪問?} {堆棧=> 主}

>檢查uc_link - 功能()結束,因爲n_switchs的以及= 2:

在返回時,對於[TID 0的第一呼叫]堆棧幀從主的 重新建立了新>

主要[TID 0的第一呼叫]彈出;再次找到engine_uc - >重置sigprocmask - > {not uninitialized access?}

在返回時,對於主堆棧幀:swapcontext()被從主的 堆棧中彈出 - >

setcontext()S回主上下文 - >{第四未初始化訪問 } {堆棧=>主}

我們回到主(),免費的東西和退出

一些參考:

https://www.gnu.org/software/libc/manual/html_node/System-V-contexts.html http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch10s07.html

注:我知道這是不是一個完整的答案,但我不希望發佈評論部分這麼長的解釋;因此張貼在這裏。

1

您必須通知valgrind堆棧的更改。讀到這裏https://github.com/lu-zero/valgrind/blob/master/memcheck/tests/linux/stack_changes.c

的例子這是正確的代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#include <ucontext.h> 
#include <valgrind/valgrind.h> 

#define STACK_SIZE (8*1024) 

int n_ucs = 1; 
int max_switchs = 10; 
int n_switchs = 0; 
int tid = 0; 

ucontext_t *ucs; 
static ucontext_t engine_uc; 

void func(int arg) 
{ 
    while (n_switchs < max_switchs) { 
     int c_tid = tid; 
     int n_tid = (tid + 1) % n_ucs; 
     n_switchs++; 
     tid = n_tid; 
     swapcontext(&ucs[c_tid], &ucs[n_tid]); 

    } 
} 

int main(int argc, char **argv) 
{ 
    if (argc > 1) 
     n_ucs = atoi(argv[1]); 
    if (argc > 2) 
     max_switchs = atoi(argv[2]); 

    ucs = malloc(sizeof(ucontext_t) * n_ucs); 

    //store the VALGRIND_STACK_REGISTER return values 
    int* valgrind_ret = malloc(n_ucs*sizeof(int)); 

    int i; 
    for (i = 0; i < n_ucs; i++) { 
     /* Create initial ucontext_t, including stack */ 
     getcontext(&ucs[i]); 

     //pass stack to valgrind 
     void* mystack = malloc(STACK_SIZE); 
     VALGRIND_STACK_REGISTER(mystack, mystack + STACK_SIZE); 

     ucs[i].uc_stack.ss_sp = mystack; 
     ucs[i].uc_stack.ss_size = STACK_SIZE; 
     ucs[i].uc_stack.ss_flags = 0; 
     ucs[i].uc_link = &engine_uc; 
     makecontext(&ucs[i], (void (*)())func, 1, i); 
    } 

    /* jump to the first uc */ 
    swapcontext(&engine_uc, &ucs[tid]); 

    /* destroy stacks */ 
    for (i = 0; i < n_ucs; i++) { 
     //valgrind stack deregister 
     VALGRIND_STACK_DEREGISTER(valgrind_ret[i]); 

     free(ucs[i].uc_stack.ss_sp); 
    } 
    free(ucs); 
    return 0; 
} 
相關問題