Thread: Passing dynamically allocated structure array to function

  1. #16
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    This:
    Code:
    struct test **tests = malloc(sizeof(tests[0]) * number_of_tests);
    and this:
    Code:
    struct test **tests = malloc(sizeof(struct test*) * number_of_tests);
    are equivalent. The former is better. So no, this should not have changed anything.
    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

  2. #17
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    That code isn't compilable. Compilable means it compiles, and hopefully it does so without any warnings, even at the maximum warning level
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=c99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c: In function ‘getInput’:
    foo.c:11:12: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
    foo.c:11:27: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
    foo.c:12:10: error: ‘i’ undeclared (first use in this function)
    foo.c:12:10: note: each undeclared identifier is reported only once for each function it appears in
    foo.c:14:9: warning: implicit declaration of function ‘scanf’ [-Wimplicit-function-declaration]
    foo.c:14:9: warning: incompatible implicit declaration of built-in function ‘scanf’ [enabled by default]
    foo.c:15:9: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
    foo.c:15:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
    foo.c:15:42: error: ‘Info’ undeclared (first use in this function)
    foo.c: In function ‘main’:
    foo.c:22:5: error: expected ‘,’ or ‘;’ before ‘struct’
    foo.c:23:5: error: ‘Info’ undeclared (first use in this function)
    foo.c:24:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
    make: *** [foo] Error 1
    Thus, I can't be sure that the changes I make to get it working will result in the exact same code you're using, that causes problems. I may find a problem my way, but it might not be the same problem.

    The easy fixes were adding the #includes for stdio.h and stdlib.h, adding the missing ; on the declaration of n in main and declaring i in getInput. However, I can't quite be certain what you're doing with the printf in getInput. I think Info should be test, but that's a guess.

    Doing all that still leaves these problems:
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=c99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c: In function ‘getInput’:
    foo.c:18:36: error: dereferencing pointer to incomplete type
    foo.c:18:48: error: dereferencing pointer to incomplete type
    foo.c:18:60: error: dereferencing pointer to incomplete type
    foo.c:18:73: error: dereferencing pointer to incomplete type
    foo.c:19:50: error: dereferencing pointer to incomplete type
    foo.c:19:62: error: dereferencing pointer to incomplete type
    foo.c:19:74: error: dereferencing pointer to incomplete type
    foo.c:19:86: error: dereferencing pointer to incomplete type
    foo.c: In function ‘main’:
    foo.c:28:47: error: dereferencing pointer to incomplete type
    foo.c:28:58: error: dereferencing pointer to incomplete type
    foo.c:28:69: error: dereferencing pointer to incomplete type
    foo.c:28:80: error: dereferencing pointer to incomplete type
    foo.c:29:47: error: dereferencing pointer to incomplete type
    foo.c:29:58: error: dereferencing pointer to incomplete type
    foo.c:29:69: error: dereferencing pointer to incomplete type
    foo.c:29:80: error: dereferencing pointer to incomplete type
    make: *** [foo] Error 1
    Looks like you declare struct stud, but use struct test. Partly my fault I think, as I renamed some stuff to make things more clear (IMO). Fixing that:
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=c99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c: In function ‘getInput’:
    foo.c:19:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘char *’ [-Wformat]
    Down to one error. Your printf format specifier for n appears to be wrong, it should be %s.

    That finally compiles, and I get a seg fault. I notice you're always printing tests[1] instead of tests[i] in getInput.

    The real problem you're having is this line:
    Code:
    tests[i] = malloc(sizeof(tests[i]));
    That doesn't quite do what you think. Remember, you have an array of pointers. Thus, tests[i] is a pointer to struct test. That means that sizeof(tests[i]) gives the size of a pointer, not the size of the struct pointed to. You're not allocating enough memory. The internal details of exactly what malloc does can vary from implementation to implementation, but what is probably happening is that malloc is giving you memory for tests[0] and tests[1] in nearly adjacent places in memory, but you're only getting, say, 4 or 8 bytes for each (size of a pointer), instead of the 100+ bytes you should get for the actual structure. This means that when you treat those addresses as actual structures, they overlap, thus modifying tests[1] seems to be modifying tests[0]. This kind of error would be very easily caught with libefence, and valgrind too, I think. Seriously, learn to use them. They're free, not very difficult, and very, very helpful.

    The general form is as follows:
    Code:
    some_type *bar = malloc(sizeof(*bar));
    Use the name of the pointer you're allocating an object for, with a single * in front of it. That gives you the size of the dereferenced pointer, i.e. the "object" (though with multiple levels of indirection that "object" may itself be a pointer). So, in summary:
    Code:
    struct test **tests = malloc(sizeof(*tests) * number_of_tests);  // allocates space for number_of_tests pointers to struct test (array elements)
    tests[i] = malloc(sizeof(*tests[i]));  // allocates space for an actual struct test, not just a pointer to struct test.

  3. #18
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by anduril462
    Code:
    tests[i] = malloc(sizeof(*tests[i]));  // allocates space for an actual struct test, not just a pointer to struct test.
    or as I suggested in post #14 and subsequently confirmed by Z0Ty in post #15:
    Code:
    tests[i] = malloc(sizeof(tests[i][0]));
    Quote Originally Posted by Z0Ty
    Also, it is same as the following?
    Code:
    tests[i] = malloc(sizeof(struct test));
    Yes, but this version is not so good as the reader needs to check the type of tests[i].
    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

  4. #19
    Registered User
    Join Date
    Jan 2014
    Posts
    9
    All clarified and everything works well now!
    Thanks for your help, I learned a lot!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dynamically allocated array
    By dre in forum C Programming
    Replies: 17
    Last Post: 08-13-2009, 06:57 PM
  2. Dynamically Allocated Array
    By vb.bajpai in forum C Programming
    Replies: 3
    Last Post: 06-17-2007, 08:40 AM
  3. Replies: 6
    Last Post: 01-16-2007, 09:21 PM
  4. passing a 2dim dynamically allocated array to a funct
    By agerealm in forum C++ Programming
    Replies: 3
    Last Post: 03-10-2004, 06:55 PM
  5. Passing dynamically allocated array to Templated Class
    By MrWizard in forum C++ Programming
    Replies: 3
    Last Post: 04-01-2002, 01:36 PM

Tags for this Thread