Valgrind, “valeur non initialisée(s)” erreur
Dans mon programme en C, je suis de l'allocation de mémoire à l'aide de malloc()
qui n'a, contrairement à calloc()
, pas initialiser la mémoire et il peut encore contenir des ordures. Surtout, dans le contexte de la répartition, je ne suis pas d'apporter des modifications à la mémoire allouée par malloc()
. (Par exemple dans une fonction pour initialiser une structure qui contient un tampon, je ne suis pas d'apporter des modifications à la mémoire tampon de la mémoire, mais plus tard).
Valgrind me donne beaucoup de ces erreurs:
- Saut conditionnel ou déplacer dépend non initialisée valeur(s)
- Utilisation de non initialisée valeur de taille 4
Je suis sûr de ne jamais lire de la mémoire qui n'a pas été initialisé dans ces cas.
Dois-je les ignorer ou est-il préférable d'initialiser la mémoire sur l'allocation des ressources? Dans le cas où je devrais les ignorer, comment puis-je désactiver ce message d'erreur dans Valgrind?
Exemple 1:
==4253== Conditional jump or move depends on uninitialised value(s)
==4253== at 0x408EB8E: vfprintf (vfprintf.c:1624)
==4253== by 0x4093C2E: printf (printf.c:35)
==4253== by 0x40624D2: (below main) (libc-start.c:226)
==4253== Uninitialised value was created by a heap allocation
==4253== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253== by 0x8048938: gk_StreamBufferNode_init (stream.c:101)
==4253== by 0x8048D0D: gk_Stream_bufferWriteProc (stream.c:252)
==4253== by 0x8048665: main (main.c:21)
Code:
int gk_StreamBufferNode_init(gk_StreamBufferNode* node, int buffer_size,
gk_AllocProc malloc) {
node->buffer = malloc(buffer_size); //line 101
if (node->buffer == NULL) {
return GKIT_FAILEDALLOC;
}
node->next = NULL;
return GKIT_NOERR;
}
Exemple 2:
==4253== Conditional jump or move depends on uninitialised value(s)
==4253== at 0x402DA39: memcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253== by 0x8048C6E: gk_Stream_bufferWriteProc (stream.c:230)
==4253== by 0x8048665: main (main.c:21)
==4253== Uninitialised value was created by a heap allocation
==4253== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4253== by 0x8048CE0: gk_Stream_bufferWriteProc (stream.c:248)
==4253== by 0x8048665: main (main.c:21)
Code:
/* ... */
int available_bytes = binfo->buffer_size - bnode->filled;
int bytes_to_go = size * count;
int offset = 0;
int node_offset = 0;
gk_StreamBufferNode* new_node;
void* destination = NULL;
void* source = NULL;
while (bytes_to_go > 0) {
destination = bnode->buffer + bnode->filled + node_offset;
source = buffer + offset;
if (available_bytes > bytes_to_go) {
memcpy(destination, source, bytes_to_go); //line 230
bnode->filled += bytes_to_go;
offset += bytes_to_go;
node_offset = bytes_to_go;
bytes_to_go = 0;
}
else {
memcpy(destination, source, available_bytes);
offset += available_bytes;
node_offset = 0;
bytes_to_go -= available_bytes;
bnode->filled += available_bytes;
#ifdef DEBUG
assert(bnode->filled == bnode->buffer_size);
#endif //DEBUG
//Allocate a new buffer node.
new_node = (gk_StreamBufferNode*) malloc(sizeof(gk_StreamBufferNode)); //line 248
if (new_node == NULL) {
return GKIT_FAILEDALLOC;
}
int success = gk_StreamBufferNode_init(new_node, binfo->buffer_size,
malloc);
if (success <= GKIT_ERROR) {
free(new_node);
return GKIT_FAILEDALLOC;
}
bnode->next = new_node;
bnode = new_node;
available_bytes = binfo->buffer_size;
}
}
if
déclaration, quelque part, aussi, parce qu'il dit "saut Conditionnel".J'ai ajouté 2 exemples. 🙂
OriginalL'auteur Niklas R | 2012-06-28
Vous devez vous connecter pour publier un commentaire.
Dans les deux cas, vous venez d'allouer de la mémoire sans l'initialiser. Le plus simple est d'utiliser
calloc
au lieu demalloc
à zéro. Cette peut être une bonne stratégie pour les cas simples, l'e.g si vous utilisez unbuffer
comme une chaîne de caractères qui sera imprimé. Pour plus compliquée cas d'utilisation d'affecter des valeurs aux champs individuels, ou encore mieux si vous avez C99 affecter l'ensemble de la structure à partir d'un composé littérale:t
. 2. N'est-ce pas une trop grande surcharge? Je suis absolument sûr de ne pas lire à partir de la mémoire qui n'a pas été définie.il connaît le type de
*t
, c'est donc une affectation d'une valeur à un objet de typetoto
. Les seuls types pour qui cela ne fonctionne pas est de type tableau,struct
, entier ou à virgule flottante types tout serait ok. Pour la lecture que vous de l'état, je suis absolument assurez-vous que vous lire la mémoire non initialisé quelque part, lorsqu'il n'est pas explicitement alors implicitement dansprintf
. Habituellement, valgrind est fiable dans ses conclusions. Non ce n'est pas un grand frais généraux, comparativement à lire si à partir de la RAM, par exemple, la RAM est de plusieurs ordres de grandeur inférieure à celle du PROCESSEUR. Dans tous les cas, prenez d'abord à droite, puis à optimiser.OriginalL'auteur Jens Gustedt
Votre code ne doit pas s'attendre à une mémoire non initialisée à contenir n'importe quelle valeur, alors conditionnelle sauts dépend de ces montre de sérieux problèmes.
Vous devez être l'initialisation de la mémoire (dans une certaine valeur connue, par exemple.
0
), ou de ne pas faire référence à son contenu, sauf s'ils ont été initialisés.Généralement, quand un programme de lit à partir de la mémoire non initialisée, l'auteur est certain qu'ils ne sont pas la lecture. Just sayin'.
Vous êtes à la lecture de la mémoire non initialisée. Le premier cas est peut-être juste un faux positif causé par une optimisation du
strlen
, probablement la lecture de 4 octets à la fois, éventuellement à lire (mais ignorant) non initialisée octets. Vous pouvez les supprimer si vous êtes sûr qu'ils sont vraiment des faux positifs (voir valgrind est--suppressions
et--gen-suppressions
options)OriginalL'auteur Hasturkun