2014-09-06 11 views
8

Ho cercato di capire perché valgrind si lamenta di "Uso del valore non inizializzato della dimensione 8" per questo piccolo programma di test che utilizza ucontexts. Fondamentalmente è un programma che crea ucodexts "n_ucs" e li scambia per "max_switch" volte.errore valgrind e ucontext. Perché "Uso del valore non inizializzato della dimensione 8"?

Ho capito "Avviso: stack di commutazione client?" (che è fondamentalmente ciò che il programma è tutto), ma non ho davvero senso a tutti "Uso del valore non inizializzato della dimensione 8"

Vorrei ottenere un aiuto per capire se gli errori di Valgrind sono falsi positivi o se questo programma ha qualcosa di fondamentalmente sbagliato. (Ne vedo molti su un programma molto più grande che usa gli stessi meccanismi, ma l'ho distillato al minimo per postare qui).

Qualsiasi aiuto è apprezzato.

Grazie,

Jack

#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; 
} 

compilare con gcc main.ce ed eseguite con ./a.out 2 2

gcc -v

Utilizzo delle specifiche integrate. COLLECT_GCC = gcc COLLECT_LTO_WRAPPER =/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper Destinazione: x86_64-linux-gnu Configurato con: ../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 Modello di discussione: posix gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)

LDD --version

LDD (Ubuntu EGLIBC 2.19-0ubuntu6.3) 2.19 Copyright (C) 2014 free software Foundation, Inc. Questo è un software gratuito ; vedere la fonte per le condizioni di copia. Non c'è garanzia; nemmeno per COMMERCIABILITÀ o IDONEITÀ PER UN PARTICOLARE SCOPO. Scritto da Roland McGrath e 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

supponendo che si sta eseguendo su un'architettura a 64 bit i puntatori sono a 64-bit (8 byte). Ciò include anche '& var' – clearlight

+2

Considerare l'utilizzo di [' calloc() '] (https://linux.die.net/man/3/calloc) per allocare la memoria, perché diversamente da' malloc() ',' calloc() 'Inizializza la memoria allocata a zero in modo implicito (non dimenticare' calloc() 'prende un secondo argomento, vedi [manpage] (https://linux.die.net/man/3/calloc)) o usa un' per() 'loop o usa' bzero() 'o' memset() 'per farlo. – clearlight

risposta

1

io ancora non capisco perché esattamente valgrind sta mostrando questi errori non inizializzate esattamente ma io darò il mio colpo migliore per spiegare quello che ho capito fino ad ora;

Durante l'esecuzione e l'analisi del programma tramite valgrind e in base alle informazioni delle pagine man di swapcontext (3) e getcontext (3), penso che non riesca a rilevare alcuni swap di contesto (non riescono a vedere il cambio di puntatore dello stack per swapcontext da tid 0 a tid 1 e lo swapcontext da tid 1 torna a tid 0)

leggere qui di seguito come: chi pila [numero di chiamate]: chiamata di funzione

Quindi, penso che traccia la funzione di chiamata è qualcosa del genere:

principale: swapcontext (principale, tid 0) ->

principale [tid 0 della prima chiamata func]: func() ->

tid 0: swapcontext (TID 0, tid 1) -> { Stack => 0 tiod}

tid 1: func() ->

swapcontext (tid 1, tid 0) -> {Stack => tiod 1}

tid 0 [2a chiamata]: func() ->

ritorno immediatamente in quanto n_switchs = 2 ->

pop tid 0 [2a chiamata]: func() stack frame dalla pila tid 1 di ->{ 1 ° accesso non inizializzata in base al Valgrind}

tid 0 [2a chiamata]: func() termina -> controlli uc_link; trova engine_uc (contesto principale) impostato lì ->

Da qui in poi le cose si fanno poco chiaro per me, ma in seguito sembra essere la probabile traccia:

resetta sigprocmask ->{2 ° accesso non inizializzata} setContext() s ritorna al contesto principale ->{3 ° accesso Uinitialized?} {Stack => principale}

0.123.516,41 mila

Al ritorno, stack frame per [tid 0 di 1 ° convocazione] spuntato dal di principale stack->

principale [tid 0 di 1 ° convocazione]: func() termina, in ragione del n_switchs = 2 -> controllare uc_link ; trova nuovamente engine_uc -> ripristina sigprocmask -> {accesso non inizializzato?}

Al ritorno, stack frame per principale: swapcontext() viene estratto dalla pila di principale ->

setContext() s di nuovo al contesto principale ->{4 ° accesso non inizializzata }? {Stack => principale}

torniamo a main(), roba gratis e uscire

Alcune referenze:

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

Nota: So che questa non è una risposta completa, ma non volevo pubblicare una lunga spiegazione tali nella sezione commenti; quindi pubblicato qui.

1

È necessario notificare a valgrind il cambio di pila. Leggi un esempio qui https://github.com/lu-zero/valgrind/blob/master/memcheck/tests/linux/stack_changes.c

Questo è il codice corretto:

#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; 
} 
Problemi correlati