1

Yesterday I asked a question so that you could help me debug a program which consists basically in reading a variable-size line from the standard input. After a while I thought I had solved all problems, but today, valgrind is still complaining.

I compiled my program with:

gcc -g -o find_all_words find_all_words.c

and then I used valgrind as follows:

valgrind --leak-check=full --show-leak-kinds=all ./find_all_words hello world

it points also to another part in the while loop of my code:

==15333== Memcheck, a memory error detector
==15333== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15333== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==15333== Command: ./find_all_words hello world
==15333== 
Enter your favourite citation: hello world, how are you today?
line = hello world, how are you today?
Input arguments:
1 = hello
2 = world
==15333== 
==15333== HEAP SUMMARY:
==15333==     in use at exit: 30,666 bytes in 189 blocks
==15333==   total heap usage: 276 allocs, 87 frees, 36,976 bytes allocated
==15333== 
==15333== 2,064 bytes in 1 blocks are possibly lost in loss record 57 of 64
==15333==    at 0x100009104: malloc_zone_malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==15333==    by 0x1004F4EFD: _objc_copyClassNamesForImage (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E8182: protocols() (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E8093: readClass(objc_class*, bool, bool) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E5C13: gc_init (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004ED24E: objc_initializeClassPair_internal(objc_class*, char const*, objc_class*, objc_class*) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004FA132: layout_string_create (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E883C: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E8300: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E82E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E82E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==15333==    by 0x1004E82E9: copySwiftV1MangledName(char const*, bool) (in /usr/lib/libobjc.A.dylib)
==15333== 
==15333== 4,096 bytes in 1 blocks are still reachable in loss record 63 of 64
==15333==    at 0x100008E3B: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
==15333==    by 0x1001E2AF5: __smakebuf (in /usr/lib/system/libsystem_c.dylib)
==15333==    by 0x1001E66D0: __srefill0 (in /usr/lib/system/libsystem_c.dylib)
==15333==    by 0x1001E67B8: __srefill (in /usr/lib/system/libsystem_c.dylib)
==15333==    by 0x1001DFA66: fgets (in /usr/lib/system/libsystem_c.dylib)
==15333==    by 0x100000A73: readline (find_all_words.c:26)
==15333==    by 0x100000E0D: main (find_all_words.c:94)
==15333== 
==15333== LEAK SUMMARY:
==15333==    definitely lost: 0 bytes in 0 blocks
==15333==    indirectly lost: 0 bytes in 0 blocks
==15333==      possibly lost: 2,064 bytes in 1 blocks
==15333==    still reachable: 4,096 bytes in 1 blocks
==15333==         suppressed: 24,506 bytes in 187 blocks
==15333== 
==15333== For counts of detected and suppressed errors, rerun with: -v
==15333== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 17 from 17)

And this is my program:

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

/**
* Gets and a variable-size line from the standard input.
*/
char * readline(){

    size_t n = 10;
    char* final = calloc(n, sizeof(char));
    final[0] = '\0';
    char* tmp; // used for allocating memory temporarily

    // constant buffer size used to store the read characters
    // before storing them in the final buffer
    char buf[10];

    while(fgets(buf, sizeof buf, stdin) != NULL) {

        if(buf[strlen(buf) - 1] == '\n') {

            if(strlen(buf) > 1) {

                if((n - strlen(final)) < (strlen(buf) + 1)) {
                    // -1 because buf contains also \n at the end
                    n = strlen(final) + strlen(buf);
                    tmp = calloc(n, sizeof(char));

                    for(int i=0; i <= strlen(final); ++i)
                        tmp[i] = final[i];

                    free(final);

                } else {
                    tmp = final;
                }

                int i, j;
                for(i = strlen(tmp), j = 0; j <= (strlen(buf) - 2); ++i, ++j)
                    tmp[i] = buf[j];

                tmp[i] = '\0';
                final = tmp;
                tmp = NULL;
            }

            break;

        } else { // no newline inserted at the end

            if((n - strlen(final)) < (strlen(buf) + 1)) {
                n *= 2;
                tmp = calloc(n, sizeof(char));

                for(int i = 0; i <= strlen(final); ++i)
                    tmp[i] = final[i];

                free(final);

            } else {
                tmp = final;
            }       

            // Starts inserting from the '\0' char
            // Insert also the '\0' at the end
            for(int i = strlen(tmp), j = 0; j <= 9; ++i, ++j)
                tmp[i] = buf[j];

            final = tmp;
            tmp = NULL;
        }
    }

    return final;
}


int main(int argc, char *argv[]){
    if(argc < 2){
        fprintf(stderr, "usage: at least one string as command-line argument.\n");
        exit(1);
    } else {

        printf("Enter your favourite citation: ");

        char *line = readline();

        printf("line = %s\n", line);

        printf("Input arguments:\n");

        for(int i=1; i < argc; ++i)
            printf("%i = %s\n", i, argv[i]);

        free(line);
    }



    return 0;
}

Thanks for any help!

nbro
  • 15,395
  • 32
  • 113
  • 196
  • Odd. I tested your code the same way you did (adding the necessary includes) and valgrind is not complaining. What is at line 26? – Julien Lopez Mar 15 '16 at 10:01
  • @JulienLopez It's the while loop... – nbro Mar 15 '16 at 10:03
  • Can you post your complete program then? There are several lines missing according to your valgrind output. – Julien Lopez Mar 15 '16 at 10:09
  • @JulienLopez This is all the code of the program with which I compiled it except from the imports...I've actually another function, but before I compiled I had already removed it from the code...It isn't actually causing problems, because even if I keep it I receive apparently the same errors, that is, in any case, there are problems in this code or valgrind is mad... – nbro Mar 15 '16 at 10:10
  • Thank you. Ok so it's not the code. Are you on OS X? – Julien Lopez Mar 15 '16 at 10:21
  • @JulienLopez Yes, I'm on OS X. I should have added the tag too, that's true. I'm going to do it. Anyway, I'm not sure if this could be a reason, but I've left the mac turned on all the night (as I usually do)... – nbro Mar 15 '16 at 10:24
  • That's it. And this is why I have no errors on Linux. :) See my answer. – Julien Lopez Mar 15 '16 at 10:27
  • @JulienLopez Ok, thank you! I'll have a look a those posts ;) – nbro Mar 15 '16 at 10:33

1 Answers1

3

Have a look here: Possible Memory Leak Valgrind in OSX El Capitan and here: Valgrind Errors on Mac OS X for printf a double.

You can safely ignore those errors in valgrind then. :)

Community
  • 1
  • 1
Julien Lopez
  • 1,794
  • 5
  • 18
  • 24