4

I have problem with extra credit section of exercise 16 of Learn C The Hard Way (http://c.learncodethehardway.org/book/ex16.html), I'm trying to convert structs so they are not using malloc. I came up with this code (I'm not sure if I should paste original code too or link is just enough):

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

struct Person {
    char *name;
    int age;
    int height;
    int weight;
};

void Person_print(struct Person who)
{
    printf("Name: %s\n", who.name);
    printf("\tAge: %d\n", who.age);
    printf("\tHeight: %d\n", who.height);
    printf("\tWeight: %d\n", who.weight);
}

int main(int argc, char *argv[])
{
    struct Person joe = {"Joe Alex", 32, 64, 140};
    struct Person frank = {"Frank Blank", 20, 72, 180};

    // print them out and where they are in memory
    printf("Joe is at memory location %p:\n", &joe);
    Person_print(joe);

    printf("Frank is at memory location %p:\n", &frank);
    Person_print(frank);

    // make everyone age 20 years and print them again
    joe.age += 20;
    joe.height -= 2;
    joe.weight += 40;
    Person_print(joe);

    frank.age += 20;
    frank.weight += 20;
    Person_print(frank);

    return 0;
}

Code compiles without any errors or warnings and works as expected. If I run it by Valgrind i get following output:

==8556== Memcheck, a memory error detector
==8556== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==8556== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==8556== Command: ./ex16
==8556==
--8556-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--8556-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--8556-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
Joe is at memory location 0x104802928:
Name: Joe Alex
==8556== Conditional jump or move depends on uninitialised value(s)
==8556==    at 0x1003FCC3F: _platform_memchr$VARIANT$Haswell (in /usr/lib/system/libsystem_platform.dylib)
==8556==    by 0x1001F0BB6: __sfvwrite (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x1001FB005: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x1002209CE: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x100220CA0: __xvprintf (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x1001F6B91: vfprintf_l (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x1001F49F7: printf (in /usr/lib/system/libsystem_c.dylib)
==8556==    by 0x100000D58: Person_print (ex16.c:16)
==8556==    by 0x100000E34: main (ex16.c:28)
==8556==
    Age: 32
    Height: 64
    Weight: 140
Frank is at memory location 0x104802910:
Name: Frank Blank
    Age: 20
    Height: 72
    Weight: 180
Name: Joe Alex
    Age: 52
    Height: 62
    Weight: 180
Name: Frank Blank
    Age: 40
    Height: 72
    Weight: 200
==8556==
==8556== HEAP SUMMARY:
==8556==     in use at exit: 38,691 bytes in 425 blocks
==8556==   total heap usage: 504 allocs, 79 frees, 44,803 bytes allocated
==8556==
==8556== LEAK SUMMARY:
==8556==    definitely lost: 16 bytes in 1 blocks
==8556==    indirectly lost: 0 bytes in 0 blocks
==8556==      possibly lost: 13,130 bytes in 120 blocks
==8556==    still reachable: 25,545 bytes in 304 blocks
==8556==         suppressed: 0 bytes in 0 blocks
==8556== Rerun with --leak-check=full to see details of leaked memory
==8556==
==8556== For counts of detected and suppressed errors, rerun with: -v
==8556== Use --track-origins=yes to see where uninitialised values come from
==8556== ERROR SUMMARY: 12 errors from 1 contexts (suppressed: 0 from 0)

I can't understand Valgrind output here, I will be very thankful for any explanation. I tried to comment out those lines in Print_person function:

/* printf("\tAge: %d\n", who.age); */
/* printf("\tHeight: %d\n", who.height); */
/* printf("\tWeight: %d\n", who.weight); */

and without them Valgrind does not find any errors, but I can't understand why.

  • What did you see when you ran it with `--leak-check=full` as suggested? – Scott Hunter Jan 08 '15 at 19:44
  • Output is the same - I ran it both with --leak-check=full and without it, saved output to files and diffed it and it's exactly the same. – Kuba Płoskonka Jan 08 '15 at 19:47
  • 1
    Which platform are you on? On some platforms, notably MacOS, Valgrind is best used with [suppression files](http://stackoverflow.com/questions/5226691/valgrind-mac-os-mem-leak?rq=1). – M Oehm Jan 08 '15 at 19:48
  • OMG, Sorry for comment about output, I used it by valgrind ./ex16 --leak-check=full which obviously didn't work ;) Tried again and gained some more output, maybe I can find something in it. Thanks for clue! I also use OSX so @MOehm thanks for link. – Kuba Płoskonka Jan 08 '15 at 19:51
  • Just out of curiosity, does this error message go away if you add `--partial-loads-ok=yes` to the Valgrind command line? – Nemo Jan 08 '15 at 20:47
  • No, it's still 12 errors ;) If I run it witch --leak-check=full then there's 29 errors, so I just ignored it for now. – Kuba Płoskonka Jan 09 '15 at 07:59

1 Answers1

2

You can ignore this warning. It's related to normal (if unusual) behavior within the C standard library.

(Specifically, the Mac OS X implementation of the memchr() function, which searches for a byte within a block of memory, optimizes memory access by reading more than one byte at a time. This may involve access to uninitialized memory beyond the end of the block, which Valgrind detects as a potential error.)