2014-09-06 6 views
8

Ich habe versucht zu verstehen, warum valgrind über "Verwendung von nicht initialisierten Wert der Größe 8" für dieses kleine Testprogramm, das ucontexts verwendet, klagt. Es ist im Grunde ein Programm, das "n_ucs" ucontexts erstellt und sie für "max_switch" -Zeiten umschaltet.Valgrind Fehler und Ucontext. Warum "Verwendung von nicht initialisierten Wert der Größe 8"?

Ich verstehe die "Warnung: Client Switching Stacks?" (Das ist im Grunde, was das Programm alles über), aber ich kann nicht wirklich Sinn all die „Verwendung von nicht initialisierten Wert der Größe 8“

machen würde Ich mag etwas Hilfe Verständnis bekommen, wenn Valgrind Fehler falsch positiv sind oder wenn dieses Programm etwas grundsätzlich falsch hat. (Ich sehe viele von ihnen auf einem viel größeren Programm, das die gleichen Mechanismen verwendet, aber ich habe es auf das Minimum destilliert, um hier zu posten).

Jede Hilfe wird geschätzt.

Danke,

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

kompilieren mit gcc main.c und laufen mit ./a.out 2 2

gcc -v

Verwenden von integrierten Spezifikationen. COLLECT_GCC = gcc COLLECT_LTO_WRAPPER =/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper Ziel: x86_64-linux-gnu Konfiguriert mit: ../src/configure -v --with-pkgversion = 'Ubuntu 4.8.2-19ubuntu1' --with-bugurl = datei: ///usr/share/doc/gcc-4.8/README.Bugs --enable-languages ​​= c, C++, java, gehen, d, fortran, objc, obj-C++ --prefix =/usr --programm-suffix = -4.8 --enable-shared --enable-linker-build-id --libexecdir =/usr/lib --ohne-included-gettext - enable-threads = posix - mit-gxx-include-dir =/usr/einschluss/C++/4.8 --libdir =/usr/lib --enable-nls --mit-sysroot =/--enable-clocale = gnu --enable-libstdcxx-debug --enable-libstdcxx-time = ja --enable-gnu-eindeutiges-objekt --disable-libmudflap --enable-plugin --mit-system-zlib --disable-browser-plugin - -enable-java-awt = gtk --enable-gtk-cairo - mit-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 - mit-arch-verzeichnis = amd64 - mit-ecj-jar =/usr/share/java/eclipse-ecj.jar --able-objc-gc --enable-multiarch --disable-werror - mit-bogen-32 = i686 - mit-abi = m64 - mit-multilib-list = m32, m64, mx32 --with-tune = generisch --enable-checking = release --build = x86_64-linux-gnu --host = x86_64-linux-gnu --target = x86_64-linux-gnu Gewindemodell: 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. Dies ist freie Software ; Informationen zum Kopieren finden Sie in der Quelle . Es gibt KEINE garantie; nicht einmal für MARKTGÄNGIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. Geschrieben von Roland McGrath und 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

Angenommen, Sie sind auf einer 64-Bit-Architektur Ihre Zeiger sind 64-Bit (8 Byte). Dazu gehört auch '& var' – clearlight

+2

Überlegen Sie, [' calloc() '] (https://linux.die.net/man/3/calloc) Ihren Speicher zuzuweisen, denn im Gegensatz zu' malloc() ',' calloc() 'initialisiert Ihren zugewiesenen Speicher implizit auf Null (vergessen Sie nicht' calloc() 'benötigt ein zweites Argument, siehe [manpage] (https://linux.die.net/man/3/calloc)) oder verwenden Sie ein' for() 'loop oder benutze' bzero() 'oder' memset() ', um es zu tun. – clearlight

Antwort

1

ich noch nicht genau verstehen, warum valgrind diese nicht initialisierte Fehler zeigt genau aber ich werde mein Bestes geben, um zu erklären, was ich bis jetzt verstanden;

Beim Ausführen und Analysieren des Programms über Valgrind und basierend auf Informationen von man pages von sapcontext (3) und getcontext (3), denke ich, dass es einige Kontextwechsel nicht erkennen kann (Stackzeigeränderungen für sapcontext nicht zu sehen) von tid 0 bis dreimal täglich 1 und dem swapcontext von tid 1 0)

Lesen als unten an tid zurück: die [Anzahl der Anruf] Stack ist: Funktionsaufruf

Also, ich denke, Trace-Funktion Anruf etwas wie dieses:

Haupt: swapcontext (Haupt, tid 0) ->

Haupt [1 func Aufruf des tid 0]: func() ->

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

tid 1: func() ->

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

tid 0 [2. Aufruf]: func() ->

Rückkehr sofort da n_switchs = 2 ->

pop tid 0 [2. Aufruf]: func() Stapelrahmen von tid 1 Stack ->{ 1. Uninitialized Zugang nach valgrind}

tid 0 [2. Aufruf]: func() beendet -> prüft uc_link; findet engine_uc (Haupt Kontext) gesetzt dort ->

Von hier aus auf die Dinge für mich unklar bekommen aber nach scheint die wahrscheinliche Spur zu sein:

setzt sigprocmask ->{2. Uninitialized Zugang} SetContext() s zurück zur Haupt Kontext ->{3. Uinitialized Zugang?} {Stapel => Haupt}

Auf dem Rückweg Stapelrahmen für [1. Aufruf des tid 0] knallte von der Haupt Stapel->

Haupt [1. Aufruf des tid 0]: func() wegen n_switchs auch beendet = 2 -> überprüfen uc_link ; findet Engine_uc wieder -> setzt sigprocmask zurück -> {nicht nicht initialisierter Zugriff?>

SetContext() s zurück zur Haupt Kontext - - swapcontext() des aus dem Haupt Stapel genommen wird>{4. Uninitialized Zugang }:}

Auf dem Rückweg, Stapelrahmen für Haupt {Stapel => Haupt}

wir zurück zu main() kommen, freies Material und Ausfahrt

Einige Referenzen:

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

Hinweis: Ich weiß, dass dies keine vollständige Antwort, aber ich wollte nicht so lange Erklärung in Kommentaren posten; daher hier gepostet.

1

Sie müssen Valgrind über die Änderung des Stapels informieren. Lesen Sie hier ein Beispiel https://github.com/lu-zero/valgrind/blob/master/memcheck/tests/linux/stack_changes.c

Dies ist der richtige Code:

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