Is there any memory leak for the implementation of array of char arrays

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite












Basically, I declared a char array to hold a maximum size of 100 char arrays.



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

int add_to_urls(char **urls, char *url)
for (int i = 0; i < 100; i++)
if (urls[i] == NULL)
urls[i] = malloc(sizeof(strlen(url) + 1));
strcpy(urls[i], url);
break;
else
//make sure we don't add same site twice
if (strcmp(urls[i], url) == 0)
printf("%s already in listn", urls[i]);



return 0;


void free_urls(char **urls)
for (int i = 0; i < 100; i++)
if (urls[i] != NULL)
free(urls[i]);
else break;



int main()
char *urls[100] = NULL;

char *url = "www.youtube.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

printf("URL: %sn", urls[0]);
printf("URL: %sn", urls[1]);

free_urls(urls);

return 0;



I'm not sure if there's any conventions of making such an array container, as I am learning how to use c. The priority is to check if there's any memory leak, what I did is iteratively release the urls[i] and urls itself will be automatically handled (I suspect).



The second thing is about improvements, what do you think might be inappropriate causing any potential troubles?







share|improve this question















  • 2




    If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
    – psychedelic_alex
    Apr 19 at 3:47










  • Code with bugs in it is specifically off-topic for this site.
    – user1118321
    Apr 19 at 5:24
















up vote
0
down vote

favorite












Basically, I declared a char array to hold a maximum size of 100 char arrays.



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

int add_to_urls(char **urls, char *url)
for (int i = 0; i < 100; i++)
if (urls[i] == NULL)
urls[i] = malloc(sizeof(strlen(url) + 1));
strcpy(urls[i], url);
break;
else
//make sure we don't add same site twice
if (strcmp(urls[i], url) == 0)
printf("%s already in listn", urls[i]);



return 0;


void free_urls(char **urls)
for (int i = 0; i < 100; i++)
if (urls[i] != NULL)
free(urls[i]);
else break;



int main()
char *urls[100] = NULL;

char *url = "www.youtube.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

printf("URL: %sn", urls[0]);
printf("URL: %sn", urls[1]);

free_urls(urls);

return 0;



I'm not sure if there's any conventions of making such an array container, as I am learning how to use c. The priority is to check if there's any memory leak, what I did is iteratively release the urls[i] and urls itself will be automatically handled (I suspect).



The second thing is about improvements, what do you think might be inappropriate causing any potential troubles?







share|improve this question















  • 2




    If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
    – psychedelic_alex
    Apr 19 at 3:47










  • Code with bugs in it is specifically off-topic for this site.
    – user1118321
    Apr 19 at 5:24












up vote
0
down vote

favorite









up vote
0
down vote

favorite











Basically, I declared a char array to hold a maximum size of 100 char arrays.



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

int add_to_urls(char **urls, char *url)
for (int i = 0; i < 100; i++)
if (urls[i] == NULL)
urls[i] = malloc(sizeof(strlen(url) + 1));
strcpy(urls[i], url);
break;
else
//make sure we don't add same site twice
if (strcmp(urls[i], url) == 0)
printf("%s already in listn", urls[i]);



return 0;


void free_urls(char **urls)
for (int i = 0; i < 100; i++)
if (urls[i] != NULL)
free(urls[i]);
else break;



int main()
char *urls[100] = NULL;

char *url = "www.youtube.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

printf("URL: %sn", urls[0]);
printf("URL: %sn", urls[1]);

free_urls(urls);

return 0;



I'm not sure if there's any conventions of making such an array container, as I am learning how to use c. The priority is to check if there's any memory leak, what I did is iteratively release the urls[i] and urls itself will be automatically handled (I suspect).



The second thing is about improvements, what do you think might be inappropriate causing any potential troubles?







share|improve this question











Basically, I declared a char array to hold a maximum size of 100 char arrays.



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

int add_to_urls(char **urls, char *url)
for (int i = 0; i < 100; i++)
if (urls[i] == NULL)
urls[i] = malloc(sizeof(strlen(url) + 1));
strcpy(urls[i], url);
break;
else
//make sure we don't add same site twice
if (strcmp(urls[i], url) == 0)
printf("%s already in listn", urls[i]);



return 0;


void free_urls(char **urls)
for (int i = 0; i < 100; i++)
if (urls[i] != NULL)
free(urls[i]);
else break;



int main()
char *urls[100] = NULL;

char *url = "www.youtube.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

url = "www.reddit.com";
add_to_urls(urls, url);

printf("URL: %sn", urls[0]);
printf("URL: %sn", urls[1]);

free_urls(urls);

return 0;



I'm not sure if there's any conventions of making such an array container, as I am learning how to use c. The priority is to check if there's any memory leak, what I did is iteratively release the urls[i] and urls itself will be automatically handled (I suspect).



The second thing is about improvements, what do you think might be inappropriate causing any potential troubles?









share|improve this question










share|improve this question




share|improve this question









asked Apr 19 at 3:19









Logan

1877




1877







  • 2




    If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
    – psychedelic_alex
    Apr 19 at 3:47










  • Code with bugs in it is specifically off-topic for this site.
    – user1118321
    Apr 19 at 5:24












  • 2




    If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
    – psychedelic_alex
    Apr 19 at 3:47










  • Code with bugs in it is specifically off-topic for this site.
    – user1118321
    Apr 19 at 5:24







2




2




If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
– psychedelic_alex
Apr 19 at 3:47




If you want to check for memory errors then I'd recommend installing Valgrind and running your program through it
– psychedelic_alex
Apr 19 at 3:47












Code with bugs in it is specifically off-topic for this site.
– user1118321
Apr 19 at 5:24




Code with bugs in it is specifically off-topic for this site.
– user1118321
Apr 19 at 5:24










1 Answer
1






active

oldest

votes

















up vote
0
down vote



accepted










You made an error here:



 urls[i] = malloc(sizeof(strlen(url) + 1));


strlen(url) + 1 is of type size_t, so you will allocate enough space for that, which could well be less than the amount you actually wanted (strlen(url) + 1).



If we fix that bug, and also change url to const char* (because it points at string literals, which are always const), then we get a clean Valgrind run from the test program.




What does the return value from add_to_urls indicate? If you meant it to be true when the url was added, then the break should be replaced with return 1.



Always check the result of malloc() is not null.



Errors and warnings should be printed to the standard error stream, not to stdout.



Your main() doesn't check that we didn't add a duplicate. In fact we did, but we never printed it.



Avoid writing constants (such as 100) in separate places if they need to agree with each other.



Instead of the break in free_urls(), we can make the test part of the loop's condition.




Improved code



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

int add_to_urls(char **urls, const char *url, size_t max_list)

for (size_t i = 0; i < max_list; i++)
if (!urls[i])
urls[i] = malloc(strlen(url) + 1);
if (!urls[i])
fprintf(stderr, "Failed to alloc for %sn", url);
return 0; /* failed allocation */

strcpy(urls[i], url);
return 1; /* we added it */

//make sure we don't add same site twice
if (strcmp(urls[i], url) == 0)
fprintf(stderr, "%s already in listn", url);
return 0; /* already present */


return 0; /* ran out of room */


void free_urls(char **urls, size_t max_list)
for (size_t i = 0; i < max_list && urls[i]; i++)
free(urls[i]);



int main()
char *urls[100] = NULL;
const size_t url_len = sizeof urls / sizeof *urls;

add_to_urls(urls, "www.youtube.com", url_len);
add_to_urls(urls, "www.reddit.com", url_len);
add_to_urls(urls, "www.reddit.com", url_len);

for (size_t i = 0; i < url_len && urls[i]; i++)
printf("URL[%zd]: %sn", i, urls[i]);


free_urls(urls, url_len);






share|improve this answer























    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192422%2fis-there-any-memory-leak-for-the-implementation-of-array-of-char-arrays%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote



    accepted










    You made an error here:



     urls[i] = malloc(sizeof(strlen(url) + 1));


    strlen(url) + 1 is of type size_t, so you will allocate enough space for that, which could well be less than the amount you actually wanted (strlen(url) + 1).



    If we fix that bug, and also change url to const char* (because it points at string literals, which are always const), then we get a clean Valgrind run from the test program.




    What does the return value from add_to_urls indicate? If you meant it to be true when the url was added, then the break should be replaced with return 1.



    Always check the result of malloc() is not null.



    Errors and warnings should be printed to the standard error stream, not to stdout.



    Your main() doesn't check that we didn't add a duplicate. In fact we did, but we never printed it.



    Avoid writing constants (such as 100) in separate places if they need to agree with each other.



    Instead of the break in free_urls(), we can make the test part of the loop's condition.




    Improved code



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

    int add_to_urls(char **urls, const char *url, size_t max_list)

    for (size_t i = 0; i < max_list; i++)
    if (!urls[i])
    urls[i] = malloc(strlen(url) + 1);
    if (!urls[i])
    fprintf(stderr, "Failed to alloc for %sn", url);
    return 0; /* failed allocation */

    strcpy(urls[i], url);
    return 1; /* we added it */

    //make sure we don't add same site twice
    if (strcmp(urls[i], url) == 0)
    fprintf(stderr, "%s already in listn", url);
    return 0; /* already present */


    return 0; /* ran out of room */


    void free_urls(char **urls, size_t max_list)
    for (size_t i = 0; i < max_list && urls[i]; i++)
    free(urls[i]);



    int main()
    char *urls[100] = NULL;
    const size_t url_len = sizeof urls / sizeof *urls;

    add_to_urls(urls, "www.youtube.com", url_len);
    add_to_urls(urls, "www.reddit.com", url_len);
    add_to_urls(urls, "www.reddit.com", url_len);

    for (size_t i = 0; i < url_len && urls[i]; i++)
    printf("URL[%zd]: %sn", i, urls[i]);


    free_urls(urls, url_len);






    share|improve this answer



























      up vote
      0
      down vote



      accepted










      You made an error here:



       urls[i] = malloc(sizeof(strlen(url) + 1));


      strlen(url) + 1 is of type size_t, so you will allocate enough space for that, which could well be less than the amount you actually wanted (strlen(url) + 1).



      If we fix that bug, and also change url to const char* (because it points at string literals, which are always const), then we get a clean Valgrind run from the test program.




      What does the return value from add_to_urls indicate? If you meant it to be true when the url was added, then the break should be replaced with return 1.



      Always check the result of malloc() is not null.



      Errors and warnings should be printed to the standard error stream, not to stdout.



      Your main() doesn't check that we didn't add a duplicate. In fact we did, but we never printed it.



      Avoid writing constants (such as 100) in separate places if they need to agree with each other.



      Instead of the break in free_urls(), we can make the test part of the loop's condition.




      Improved code



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

      int add_to_urls(char **urls, const char *url, size_t max_list)

      for (size_t i = 0; i < max_list; i++)
      if (!urls[i])
      urls[i] = malloc(strlen(url) + 1);
      if (!urls[i])
      fprintf(stderr, "Failed to alloc for %sn", url);
      return 0; /* failed allocation */

      strcpy(urls[i], url);
      return 1; /* we added it */

      //make sure we don't add same site twice
      if (strcmp(urls[i], url) == 0)
      fprintf(stderr, "%s already in listn", url);
      return 0; /* already present */


      return 0; /* ran out of room */


      void free_urls(char **urls, size_t max_list)
      for (size_t i = 0; i < max_list && urls[i]; i++)
      free(urls[i]);



      int main()
      char *urls[100] = NULL;
      const size_t url_len = sizeof urls / sizeof *urls;

      add_to_urls(urls, "www.youtube.com", url_len);
      add_to_urls(urls, "www.reddit.com", url_len);
      add_to_urls(urls, "www.reddit.com", url_len);

      for (size_t i = 0; i < url_len && urls[i]; i++)
      printf("URL[%zd]: %sn", i, urls[i]);


      free_urls(urls, url_len);






      share|improve this answer

























        up vote
        0
        down vote



        accepted







        up vote
        0
        down vote



        accepted






        You made an error here:



         urls[i] = malloc(sizeof(strlen(url) + 1));


        strlen(url) + 1 is of type size_t, so you will allocate enough space for that, which could well be less than the amount you actually wanted (strlen(url) + 1).



        If we fix that bug, and also change url to const char* (because it points at string literals, which are always const), then we get a clean Valgrind run from the test program.




        What does the return value from add_to_urls indicate? If you meant it to be true when the url was added, then the break should be replaced with return 1.



        Always check the result of malloc() is not null.



        Errors and warnings should be printed to the standard error stream, not to stdout.



        Your main() doesn't check that we didn't add a duplicate. In fact we did, but we never printed it.



        Avoid writing constants (such as 100) in separate places if they need to agree with each other.



        Instead of the break in free_urls(), we can make the test part of the loop's condition.




        Improved code



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

        int add_to_urls(char **urls, const char *url, size_t max_list)

        for (size_t i = 0; i < max_list; i++)
        if (!urls[i])
        urls[i] = malloc(strlen(url) + 1);
        if (!urls[i])
        fprintf(stderr, "Failed to alloc for %sn", url);
        return 0; /* failed allocation */

        strcpy(urls[i], url);
        return 1; /* we added it */

        //make sure we don't add same site twice
        if (strcmp(urls[i], url) == 0)
        fprintf(stderr, "%s already in listn", url);
        return 0; /* already present */


        return 0; /* ran out of room */


        void free_urls(char **urls, size_t max_list)
        for (size_t i = 0; i < max_list && urls[i]; i++)
        free(urls[i]);



        int main()
        char *urls[100] = NULL;
        const size_t url_len = sizeof urls / sizeof *urls;

        add_to_urls(urls, "www.youtube.com", url_len);
        add_to_urls(urls, "www.reddit.com", url_len);
        add_to_urls(urls, "www.reddit.com", url_len);

        for (size_t i = 0; i < url_len && urls[i]; i++)
        printf("URL[%zd]: %sn", i, urls[i]);


        free_urls(urls, url_len);






        share|improve this answer















        You made an error here:



         urls[i] = malloc(sizeof(strlen(url) + 1));


        strlen(url) + 1 is of type size_t, so you will allocate enough space for that, which could well be less than the amount you actually wanted (strlen(url) + 1).



        If we fix that bug, and also change url to const char* (because it points at string literals, which are always const), then we get a clean Valgrind run from the test program.




        What does the return value from add_to_urls indicate? If you meant it to be true when the url was added, then the break should be replaced with return 1.



        Always check the result of malloc() is not null.



        Errors and warnings should be printed to the standard error stream, not to stdout.



        Your main() doesn't check that we didn't add a duplicate. In fact we did, but we never printed it.



        Avoid writing constants (such as 100) in separate places if they need to agree with each other.



        Instead of the break in free_urls(), we can make the test part of the loop's condition.




        Improved code



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

        int add_to_urls(char **urls, const char *url, size_t max_list)

        for (size_t i = 0; i < max_list; i++)
        if (!urls[i])
        urls[i] = malloc(strlen(url) + 1);
        if (!urls[i])
        fprintf(stderr, "Failed to alloc for %sn", url);
        return 0; /* failed allocation */

        strcpy(urls[i], url);
        return 1; /* we added it */

        //make sure we don't add same site twice
        if (strcmp(urls[i], url) == 0)
        fprintf(stderr, "%s already in listn", url);
        return 0; /* already present */


        return 0; /* ran out of room */


        void free_urls(char **urls, size_t max_list)
        for (size_t i = 0; i < max_list && urls[i]; i++)
        free(urls[i]);



        int main()
        char *urls[100] = NULL;
        const size_t url_len = sizeof urls / sizeof *urls;

        add_to_urls(urls, "www.youtube.com", url_len);
        add_to_urls(urls, "www.reddit.com", url_len);
        add_to_urls(urls, "www.reddit.com", url_len);

        for (size_t i = 0; i < url_len && urls[i]; i++)
        printf("URL[%zd]: %sn", i, urls[i]);


        free_urls(urls, url_len);







        share|improve this answer















        share|improve this answer



        share|improve this answer








        edited Apr 19 at 8:26


























        answered Apr 19 at 8:09









        Toby Speight

        17.5k13489




        17.5k13489






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f192422%2fis-there-any-memory-leak-for-the-implementation-of-array-of-char-arrays%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Python Lists

            Aion

            JavaScript Array Iteration Methods