Thread: C double pointer dumping core

  1. #1
    Registered User
    Join Date
    Jun 2017
    Posts
    18

    C double pointer dumping core

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <strings.h>
    #include <stdlib.h>
    #include <malloc.h>
    
    char **teststr2 = NULL;
    char **testfn3(char **);
    
    int main()
    {
     int i = 0;
     teststr2 = testfn3((char **)teststr2);
     for(i = 0; i < 20; i++) {printf("%d ++ %s\n", i, teststr2[i]);}
     /*Free memory:*/
     for(i = 0; i < 20; i++) {free(teststr2[i]);}
     free(teststr2);
    }
    
    char **testfn3(char **tests1)
    {
     int i;
     tests1 = calloc(21, sizeof(int));
     for(i = 0; i < 20; i++) {tests1[i] = calloc(6, sizeof(int)); tests1[i] = "Hello";}
     for(i = 0; i < 20; i++) {printf("%d = %s\n", i, tests1[i]);}
     return tests1;
    }
    This is the sample code. Using structures and single pointer works absolutely fine.

    However, this code dumps core, if I comment the value assignment for tests1[i] = "Hello";, then the first two values of the pointers 0 and 1 have some random values as below
    0 = @��
    1 = ���
    2 =
    3 =
    4 =
    5 =
    6 =
    7 =
    8 =
    9 =
    10 =
    11 =
    12 =
    13 =
    14 =
    15 =
    16 =
    17 =
    18 =
    19 =

    I am using calloc and not malloc, which assigns similar variables to other parts of the pointer array.

    Any comments would be much appreciated?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Your code doesn't make any sense.
    Presumably you mean something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    char **f() // no need to pass the variable in
    {
        char **t = calloc(20, sizeof *t); // use the dereferenced variable to get the size
        for (int i = 0; i < 20; i++) {
            t[i] = calloc(6, sizeof **t);
            strcpy(t[i], "Hello"); // you need to use strcpy to copy a string
        }
        return t;
    }
     
    int main()
    {
        char **t = f();
        for (int i = 0; i < 20; i++)
            printf("%2d: %s\n", i, t[i]);
        for (int i = 0; i < 20; i++)
            free(t[i]);
        free(t);
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    505
    C doesn't have pass by reference. It has pass by value. Any arguuments you pass are copied to the local variables in the argument list, and disappear on function return. So assigning the result of a malloc() call to an argument won't do what you want.

    We fake up pass by reference in C by using pointers. This is one of the main reasons for using pointers. If you pass the address of a variable, the pointer is copied, but the variable it points to is not. So you can modify the variable pointed to.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    Registered User
    Join Date
    Jun 2017
    Posts
    18
    Thank you John.
    The problem was at the memory allocation and value assignment. I used the deferencing pointer in calloc as you showed in your example and value assignment worked just fine with strcpy or sprintf but not with '='.

  5. #5
    Registered User
    Join Date
    Jun 2017
    Posts
    18
    Thank you Malcolm. I did reasoned myself about assigning values to memory allocated variables, however, the memory allocation based on deferencing variable is something that I have not thought about which John has shown in his example.

  6. #6
    Registered User
    Join Date
    Jun 2017
    Posts
    18

    working code

    My final working code below
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <strings.h>
    #include <stdlib.h>
    #include <malloc.h>
     
    char **teststr2 = NULL;
    char **testfn3(char **);
     
    int main()
    {
     int i = 0;
     teststr2 = testfn3((char **)teststr2);
     for(i = 0; i < 20; i++) {printf("%d ++ %s\n", i, teststr2[i]);}
     /*Free memory:*/
     for(i = 0; i < 20; i++) {free(teststr2[i]);}
     free(teststr2);
    }
     
    char **testfn3(char **tests1)
    {
     int i;
     tests1 = calloc(21, sizeof(*tests1));
    
     for(i = 0; i < 20; i++) {tests1[i] = calloc(6, sizeof(**tests1)); /*Also works with int*/ sprintf(tests1[i], "Hello";}
    
     for(i = 0; i < 20; i++) {printf("%d = %s\n", i, tests1[i]);}
     return tests1;
    }

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by tnethaji
    My final working code below
    Notice that in john.c's code, there was no parameter, and even the comment "no need to pass the variable in". This is the right approach because you are neither using the value of the parameter (an "in" or "input" parameter) nor storing the result via the pointer parameter (and "out" or "output" parameter). What you're doing instead is declaring a local variable for use within the function, so you should just declare an ordinary local variable rather than declaring it as a parameter.

    If you did want to pass teststr2 as an argument, then there is no point casting it to char** because it is already a char**.

    Also, you need to indent and generally format your code properly (at least two spaces per indent level - I'd suggest four; don't place multiple statements on the same line), and avoid having an unnecessary global variable.

    Note that <malloc.h> is non-standard (or pre-standard). You don't need it since malloc, realloc, and free are available by including <stdlib.h> so you should remove it. <strings.h> is non-standard, but it is POSIX standard. You're not using anything from <strings.h>, but maybe you're using them in a larger piece of code that this is from.
    Last edited by laserlight; 07-19-2020 at 05:12 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Jun 2017
    Posts
    18
    Hi Laserlight, Thank you for sharing your knowledge, much appreciated. Indeed this is a sample rough code to fit a bigger puzzle that will be further optimised. Passing of string is not the same variable, but in this code it is.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linked list program dumping core when executed.
    By V17 in forum C Programming
    Replies: 6
    Last Post: 09-03-2011, 02:14 PM
  2. Double liked list and double pointer
    By saillesh.sabari in forum C Programming
    Replies: 1
    Last Post: 12-10-2010, 11:03 AM
  3. Replies: 3
    Last Post: 10-30-2009, 04:41 PM
  4. Enable core dumping
    By steve1_rm in forum C Programming
    Replies: 3
    Last Post: 01-21-2009, 10:41 AM
  5. program segfaults without dumping a core
    By ladar in forum C Programming
    Replies: 4
    Last Post: 04-04-2005, 11:21 AM

Tags for this Thread