Thread: allocating memory with malloc

  1. #1
    UK2
    Join Date
    Sep 2003
    Posts
    112

    allocating memory with malloc

    Hello,

    I am just wondering about this line.

    As unsigned int is 4 bytes. Am I creating a block of 3 unsigned int.

    So the pointer will contain 3 blocks of unsigned int's?

    Code:
     ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    Also do I need to dereference the pointer sizeof(*ptrVP)?
    Code:
    static const unsigned int NUMBER_OF_PORTS = 3;
    typedef unsigned int *pVPGroups;
     
    int main(int argc, char** argv)
    {
    	pVPGroups ptrVP;
    	int size = sizeof(ptrVP);
    
        ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    
    	size = sizeof(ptrVP);
    	return 0;
    }
    Many thanks,

  2. #2
    Technical Lead QuantumPete's Avatar
    Join Date
    Aug 2007
    Location
    London, UK
    Posts
    894
    First of all, this isn't C++, it's C.
    Secondly, don't cast the return value of malloc.
    Thirdly, initialise all your variables!

    Also, I wouldn't ever put a * into a typedef, but that might just be me.
    Yes, you'll need the dereference operator in the sizeof() call. Otherwise sizeof will return the size of the pointer (which on most 32-bit OS is 4 bytes). In this case however, it makes no difference, since your unsigned int is most probably also 4 bytes, so in either case size will contain 4.

    QuantumPete
    P.S. Interestingly, you can dereference a NULL pointer if you use it in a sizeof() call.
    "No-one else has reported this problem, you're either crazy or a liar" - Dogbert Technical Support
    "Have you tried turning it off and on again?" - The IT Crowd

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by QuantumPete View Post
    Also, I wouldn't ever put a * into a typedef, but that might just be me.
    I concur.

    Yes, you'll need the dereference operator in the sizeof() call. Otherwise sizeof will return the size of the pointer (which on most 32-bit OS is 4 bytes). In this case however, it makes no difference, since your unsigned int is most probably also 4 bytes, so in either case size will contain 4.
    But still bad practice and will break the code if the size of the data type you use changes (ie switching from int to short).

    P.S. Interestingly, you can dereference a NULL pointer if you use it in a sizeof() call.
    Yes, sizeof merely evaluates the argument, not actually executing it...
    So it sees var and evaluates its type, and if you put * before a var of type T*, then it is simply evaluated as T.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Maybe I am not too clear.

    But is this code creating a pointer to an array of 3 unsigned int objects?
    Code:
    ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    I was compiling on CodeBlocks GCC. I got a compile error as I didn't cast.

    Anyway I thought malloc returns a void*. I know that using void* is bad practice.

    Thanks,

  5. #5
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Maybe I am not too clear.

    But is this code creating a pointer to an array of 3 unsigned int objects?
    Code:
    ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    I was compiling on CodeBlocks GCC. I got a compile error as I didn't cast.

    Anyway I thought malloc returns a void*. I know that using void* is bad practice.

    Thanks,

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by QuantumPete View Post
    Also, I wouldn't ever put a * into a typedef, but that might just be me.
    It's just you. Try to declare a pointer to pointer to function (so you can dynamically create an array of pointers to function) and you will find a typedef (for the type pointer to the particular function) very helpful.
    Quote Originally Posted by QuantumPete View Post
    Yes, you'll need the dereference operator in the sizeof() call. Otherwise sizeof will return the size of the pointer (which on most 32-bit OS is 4 bytes). In this case however, it makes no difference, since your unsigned int is most probably also 4 bytes, so in either case size will contain 4.
    You're advocating an extremely poor practice here.

    It will make a difference if you ever have to migrate between compilers or operating systems. There were quite a few people in the days before 32 bit operating systems who assumed integer and pointer types were 16 bit (2 8-bit bytes). Porting their code to 32 bit systems was a pain. Making your assumption (that unsigned int and size_t are both of size 4 bytes) will, in a similar fashion, make things break should your code need to be migrated to a 64 bit system (which are not common, but are hardly rare either at present).
    Quote Originally Posted by QuantumPete View Post
    Interestingly, you can dereference a NULL pointer if you use it in a sizeof() call.
    No you can't.

    Firstly, sizeof is not a function call: it is a compile-time operator that evaluates, at compile time, the size of its operand, not it's value. Consider the fact that the expressions "sizeof(foo)" and "sizeof foo" are equivalent.

    Computing sizeof(*pointer) computes the size of whatever pointer points at. It does not evaluate pointer and certainly does not dereference it.
    Last edited by grumpy; 12-17-2008 at 06:47 AM.

  7. #7
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Maybe I am not too clear.

    But is this code creating a pointer to an array of 3 unsigned int objects?
    Code:
    ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    I was compiling on CodeBlocks GCC. I got a compile error as I didn't cast.

    Anyway I thought malloc returns a void*. I know that using void* is bad practice.

    Thanks,

  8. #8
    UK2
    Join Date
    Sep 2003
    Posts
    112
    A problem with my Internet.

    Please ignore duplicated posts.

    Thanks

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by grumpy View Post
    It's just you. Try to declare a pointer to pointer to function (so you can dynamically create an array of pointers to function) and you will find a typedef (for the type pointer to the particular function) very helpful.
    Code:
    typedef float (fnc_ptr)(int a, char c, double d);
    
    void foo(int a, char c, double d) { }
    
    int main()
    {
        fnc_ptr* my_foo_ptr = &foo;
        my_foo_ptr(1, 'a', 10.0);
    }
    Tada!
    No * in the typedef!
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You will get enough memory for three things-that-ptrVP-points-to, so in this case three unsigned ints.

    If you are going to typedef, you should use it:
    Code:
     ptrVP = (pVPGroups) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    This way when/if your typedef changes, you won't have to change all this as well.

    Casting malloc is required in C++ (and not in plain C). On the other hand, if you are intending to write C++, why not use new instead of malloc? (Answer: because your typedef is set up the wrong way for that to work.)

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by steve1_rm View Post
    But is this code creating a pointer to an array of 3 unsigned int objects?
    Code:
    ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    The strictly correct answer is "no". The practical answer is that ptrVP can be used as if it is an array of three unsigned int (as long as the malloc() call succeeds, and doesn't return NULL).

    The malloc() call allocates, and returns the address of, a block of memory that is of size NUMBER_OF_PORTS * sizeof(*ptrVP), which (in your code) works out as the same size as a block of three unsigned ints.

    ptrVP is a pointer that holds the address of that memory block, converted to be of type "pointer to ptrVP". That pointer can be dereferenced and treated as if it is an array of three unsigned ints. So ptrVP[0], ptrVP[1], and ptrVP[2] allow access to distinct unsigned integers that are located within that memory block (and adjacent to each other in memory).

    The concern here is that a pointer and an array are distinct things, but they can be treated as if they are equivalent in some contexts. This will lead many people to mistakenly inform you that a pointer and an array are the same thing.

    Quote Originally Posted by steve1_rm View Post
    I was compiling on CodeBlocks GCC. I got a compile error as I didn't cast.
    That probably means that CodeBlocks is configured to run gcc as a C++ compiler (C++ does not allow an implicit conversion of a void pointer to other pointer types; C does). If you configure CodeBlocks to run gcc as a C compiler, you will not get that error. You'll have to read the documentation for CodeBlocks to work out how to do that.
    Quote Originally Posted by steve1_rm View Post
    Anyway I thought malloc returns a void*.
    It does.
    Quote Originally Posted by steve1_rm View Post
    I know that using void* is bad practice.
    Like any language feature, it's good practice if you use it properly and bad practice if you misuse it.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    No you can't.
    That depends on what he means; from the context it looks as if he only means that checking for null isn't necessary.

    *shrug*

    Firstly, sizeof is not [...] operand, not it's value.
    Computing [...] pointer points at.
    I'm not exactly sure if you are saying what I think you are saying or not, but for the sake of argument, Elysia's 'sizeof' explanation is much closer to the reality of C++. For any given declaration of 'T * t;', 'sizeof(*t)' should be the same as 'sizeof(T)'. That is, what 't' may actually point to, the runtime value, is irrelevant to the calculation.

    I only offer this because of the way I interpreted the statement at first; the 'sizeof' operator absolutely can't be used in polymorphic constructs--template based polymorphism aside.

    Soma

  13. #13
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by steve1_rm View Post
    Hello,

    Maybe I am not too clear.

    But is this code creating a pointer to an array of 3 unsigned int objects?
    Code:
    ptrVP = (unsigned int*) malloc(NUMBER_OF_PORTS * sizeof(*ptrVP));
    I was compiling on CodeBlocks GCC. I got a compile error as I didn't cast.

    Anyway I thought malloc returns a void*. I know that using void* is bad practice.

    Thanks,
    "using void * is bad practice"?? void pointers are fine to "use" under the right circumstances, and certainly casting a void pointer to something else is only meaningful if "something else" is not a pointer [that applies to C, C++ is different - but then we shouldn't use malloc anyways].

    If you get a compiler warning for that line you are doing one of two things wrong:
    1. You are not including stdlib.h.
    2. You are compiling C code with as C++ (or using C code in a C++ project).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  14. #14
    UK2
    Join Date
    Sep 2003
    Posts
    112
    Hello,

    Sorry, this should have been posted in the C++ forum. ):

    So my pointer points to a block of 3 integers.
    Code:
    size = sizeof(*ptrVP);
    I thought this would be 12 bytes. (3 * 4). But only displays 4. As I am dereferencing its pointing to the memory block of 3 integers. However, it displayes only 4. Why?

    So I can access them, like I would do an array. My code below.
    However, I have on purpose overrun the array to go into a forth element. My program did not crash.
    Code:
        ptrVP[0] = 10;
        ptrVP[1] = 20;
        ptrVP[2] = 30;
        ptrVP[3] = 40;
    
        std::cout << "ptrVP[0]: " << ptrVP[0] << std::endl;
        std::cout << "ptrVP[1]: " << ptrVP[1] << std::endl;
        std::cout << "ptrVP[2]: " << ptrVP[2] << std::endl;
        std::cout << "ptrVP[3]: " << ptrVP[3] << std::endl;
    Using pointer arithmetic. Would this be the same as above.
    Code:
     *ptrVP = 10;
        std::cout << "ptr 10: " << *ptrVP << std::endl;
        ptrVP++;
        *ptrVP = 20;
        std::cout << "ptr 20: " << *ptrVP << std::endl;
        ptrVP++;
        *ptrVP = 30;
        std::cout << "ptr 30: " << *ptrVP << std::endl;
    Many thanks,
    Last edited by steve1_rm; 12-17-2008 at 10:33 AM. Reason: Add detail

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by steve1_rm
    As I am dereferencing its pointing to the memory block of 3 integers. However, it displayes only 4. Why?
    The pointer points to one integer that happens to be in a block of 3 integers. We often say that a pointer points to an array when we really mean that the pointer points (or can point) to some element in an array.
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. glibc detected malloc(): memory corruption
    By totalnewbie in forum C Programming
    Replies: 6
    Last Post: 01-12-2009, 06:21 AM
  2. allocating memory in constructor
    By Micko in forum C++ Programming
    Replies: 3
    Last Post: 08-25-2004, 07:45 AM
  3. malloc returning NULL with plenty of memory
    By ... in forum C Programming
    Replies: 3
    Last Post: 03-15-2004, 01:28 AM
  4. Allocating Memory for a Structure
    By surfxtc79 in forum C Programming
    Replies: 4
    Last Post: 06-05-2003, 11:40 AM
  5. Allocating memory for a structure member
    By dalek in forum C++ Programming
    Replies: 2
    Last Post: 05-15-2003, 06:56 AM