valgrind - Address ---- is 0 bytes after a block of size 8 alloc'd
Asked Answered
G

3

43

First, I know similar questions have been asked. However, I'd like to have a more general simple question with really primitive C data types. So here it is.

In main.c I call a function to populate those string:

int
main (int argc, char *argv[]){

    char *host = NULL ;
    char *database ;
    char *collection_name;
    char *filename = ""; 
    char *fields = NULL;
    char *query = NULL;
    ...

    get_options(argc, argv, &host, &database, &collection_name, &filename, 
                &fields, &query, &aggregation);

Inside get_options:

if (*filename == NULL ) {
   *filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+4);
    strcpy(*filename, *collection_name);
    strcat(*filename, ".tde");  # line 69 
}

My program works fine, but then Valgrind tells me I'm doing it wrong:

==8608== Memcheck, a memory error detector
==8608== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==8608== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==8608== Command: ./coll2tde -h localhost -d test -c test
==8608== 
==8608== Invalid write of size 1
==8608==    at 0x403BE2: get_options (coll2tde.c:69)
==8608==    by 0x402213: main (coll2tde.c:92)
==8608==  Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd
==8608==    at 0x4C28BED: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x4C28D6F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==8608==    by 0x403BBC: get_options (coll2tde.c:67)
==8608==    by 0x402213: main (coll2tde.c:92)

Can you explain the error Address 0xa2edd18 is 0 bytes after a block of size 8 alloc'd? How can I solve this issue?

Gavial answered 24/12, 2014 at 11:36 Comment(1)
For what it's worth, I found this error message confusing because I mistook the meaning of "after". I thought it meant "after the time the block was allocated", but of course it actually means "in the memory following the allocated block". In other words: Address 0x... appears immediately (0 bytes) after an alloc'd block of size 8Bawdy
H
60

strcpy adds a null terminator character '\0'. You forgot to allocate space for it:

*filename = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);

You need to add space for 5 characters: 4 for ".tde" suffix, and one more for the '\0' terminator. Your current code allocates only 4, so the last write is done into the space immediately after the block that you have allocated for the new filename (i.e. 0 bytes after it).

Note: Your code has a common problem - it assigns the results of realloc directly to a pointer being reallocated. This is fine when realloc is successful, but creates a memory leak when it fails. Fixing this error requires storing the result of realloc in a separate variable, and checking it for NULL before assigning the value back to *filename:

char *tmp = (char*)realloc(*filename, strlen(*collection_name)*sizeof(char)+5);
if (tmp != NULL) {
    *filename = tmp;
} else {
    // Do something about the failed allocation
}

Assigning directly to *filename creates a memory leak, because the pointer the *filename has been pointing to below would become overwritten on failure, becoming non-recoverable.

Humidistat answered 24/12, 2014 at 11:39 Comment(6)
douh! I tried this before, and for some reason I remove it. So I need to be more careful here! But why the vague English? If my newly created string is larger by 1, why does valgrind say: 0 bytes after ... ?Gavial
Ok, you already saw it coming. So, 0 bytes after is Valgrind developers way to tell me in plain English: 'It's adjacent', or "directly after it".Gavial
@Oz123: 0 bytes after is as correct as 42 bytes after, isn't it?Elspet
@Oz123 Let's say the block starts at 0x8000 and is 8 bytes long. Then the last valid address of the block would be 0x8007, and 0x8008 would be the first invalid address after it. When valgrind sees a write at 0x8008, it reports it as a write to an initial byte of the illegal block as if it were an array of bytes, and it uses zero-based notation to report an offset.Humidistat
@Ac3_DeXt3R "Similar" is not specific enough. Ask a new question, and provide all the details.Humidistat
@dasblinkenlight, Yeah, but again it will marked duplicate!Merozoite
B
5

I just had this message because I had changed a class (added a field, so I had changed its size) and not rebuilt all sources that included the header. So some modules still tried to use the old size.

Borgia answered 2/12, 2020 at 13:48 Comment(0)
F
5

Share what I learned about this issue.

First, the error message is misleading, especially, the word after. At the beginning, I thought it means something occurs after (in time level) I allocated some memory block. But in fact, it means you are reading data from some random memory address. And that random memory is just after(in the address space) the memory block you allocated.

Based on my experience, typically it happens when the index of array is going out of range.

Let's take a look at the following simple demo code:

#include <stdlib.h>
#include <stdio.h>

int main() {
    int *x = (int*)malloc(sizeof(int));
    x += 3; // x now points to invalid memory(some random location)
    printf("%d\n", *x); // read from an invalid location of memory
    *x = 4;             // write to an invalid location of memory
    free(x - 3);
    return EXIT_SUCCESS;

}

which produces the following error message when running the valgrind memo check

==4720== Invalid read of size 4
==4720==    at 0x1091AC: main (memo2.c:7)
==4720==  Address 0x4a5204c is 8 bytes after a block of size 4 alloc'd
==4720==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4720==    by 0x10919E: main (memo2.c:5)
==4720==
0
==4720== Invalid write of size 4
==4720==    at 0x1091C5: main (memo2.c:8)
==4720==  Address 0x4a5204c is 8 bytes after a block of size 4 alloc'd
==4720==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==4720==    by 0x10919E: main (memo2.c:5)
Farnesol answered 14/9, 2022 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.