Thread: Dynamic mem allocation, how to get it right?

  1. #1
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485

    Dynamic mem allocation, how to get it right?

    I have tried to dynamically set the size of an array depending on a input fileīs size.
    What I have done is, first using fseek() and ftell() to fetch the start and end of the data in the file.
    I then subrtact start from end and store that in the variable size.

    What I would like to know now is if using size in an array declaration actually works as I expect it to or if I have to use malloc().

    This is what I tried first:

    Code:
    UInt8 dataArray[size];
    
    // where size is the previously unknown size of the file or data
    I wasnīt actually sure if this would work under all conditions, so I tried malloc like this:
    Code:
    UInt8 *dataArray = malloc(size);
    void *dataPt = NULL;
    
    dataPt = &dataArray;
    Iīm trying to use the void pointer to access different places in dataArray by increment itīs value here.

    Code:
    	for(dataCounter = 0; dataCounter < 120; dataCounter++) {
    			data[i].data[dataCounter] = *dataPt;
    			dataPt++;
    		}
    This gives me this warning: assignment makes integer from pointer without a cast

    If I try to cast it Iīm informed that I should not attempt to cast a void pointer? I thought that was what they where good for.











    EDIT: This was weird, I just tried to compile this again and got a new error and warning like this:

    warning: dereferencing ‘void *’ pointer
    error: void value not ignored as it ought to be
    Last edited by Subsonics; 02-06-2009 at 09:58 PM.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    If what you want is an int*, use and int*.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by MK27 View Post
    If what you want is an int*, use and int*.
    Do you mean when I declare the pointer or when I attemt to dereference it?

    If I give the same data type to the pointer and the array in the declaration I get a warning when I try to assign the address to it like this.

    dataPt = &inData;

    warning: assignment from incompatible pointer type

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
    	int size=atoi(argv[1]), dataray[size], *ptr=dataray, i;
    	for (i=0; i<size; i++) {
    		*ptr=i;
    		printf("%d\n",dataray[i]);
    		ptr++;
    	}
    	
    	return 0;
    }
    Compiles with no errors.
    ./a.out 4
    0
    1
    2
    3
    Last edited by MK27; 02-06-2009 at 10:57 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MK27
    Compiles with no errors.
    Though there might be an error if one were compiling with respect to the 1990 edition of the C standard since a variable length array is used, but it would be fine with C99. Also, atoi() is found in <stdlib.h>, which was not included. There is also a potential problem in that argv[1] would be a null pointer if the user runs the program without any command line arguments.
    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

  6. #6
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by MK27 View Post
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
    	int size=atoi(argv[1]), dataray[size], *ptr=dataray, i;
    	for (i=0; i<size; i++) {
    		*ptr=i;
    		printf("%d\n",dataray[i]);
    		ptr++;
    	}
    	
    	return 0;
    }
    If itīs ok to use a variable with unknown value at compile time to declare an array thatīs good news. It worked for me as well, but I just wasnīt sure. Most of the time I have seen people using malloc() to do this. Also I might be missing something but it seems like *ptr isnīt actually doing anything, my problem comes in when I try to dereference the pointer to assign the value to a variable. Anyway if I can achive this without pointers and malloc() Iīm going to stick with that. But it would be interesting to know how it could be achived.

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    The one with malloc is almost exactly the same (now stdlib.h is definitely needed):
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
    	int size=atoi(argv[1]), *dataray=malloc(size*sizeof(int)), *ptr=dataray, i;
    	for (i=0; i<size; i++) {
    		*ptr=i;
    		printf("%d\n",dataray[i]);
    		ptr++;
    	}
    	free(dataray);
    	
    	return 0;
    }
    Remember, if you don't give an argument it will seg fault.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Subsonics
    If itīs ok to use a variable with unknown value at compile time to declare an array thatīs good news. It worked for me as well, but I just wasnīt sure.
    As I noted in post #5, that is the variable length array feature introduced in the 1999 edition of the C Standard. There are limitations, e.g., the array cannot be expanded, unlike what you can do with say, realloc().

    For a somewhat more robust version of MK27's malloc() example:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stddef.h>
    
    int main(int argc, char *argv[]) {
        size_t size;
        int *data;
        size_t i;
    
        if (argc < 2) {
            puts("Please provide a non-negative integer command line argument.");
            return 0;
        }
    
        size = atol(argv[1]);
        data = malloc(size * sizeof(*data));
        if (data == NULL) {
            fprintf(stderr, "Error: unable to allocate memory.\n");
            return EXIT_FAILURE;
        }
    
        for (i = 0; i < size; ++i) {
            data[i] = i;
            printf("%d\n", data[i]);
        }
    
        free(data);
    
        return 0;
    }
    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

  9. #9
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by laserlight View Post
    As I noted in post #5, that is the variable length array feature introduced in the 1999 edition of the C Standard. There are limitations, e.g., the array cannot be expanded, unlike what you can do with say, realloc().
    I somehow missed that earlier, I guess using it in a function that might be called several times during execution could mean trouble if filesizes increase. Iīm going to experiment with this for a bit, thanks both of you for your input.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    UInt8* dataArray = malloc(size);
    void* dataPt = NULL;
    dataPt = &dataArray;
    This now stores the address of the pointer dataArray inside dataPt, so essentially it stores an Uint8**, masqueraded as void*.

    Code:
    	for(dataCounter = 0; dataCounter < 120; dataCounter++) {
    			data[i].data[dataCounter] = *dataPt;
    			dataPt++;
    		}
    This gives me this warning: assignment makes integer from pointer without a cast
    EDIT: This was weird, I just tried to compile this again and got a new error and warning like this:

    warning: dereferencing ‘void *’ pointer
    error: void value not ignored as it ought to be
    I don't know what exactly data & co are, but I do spot one problem.
    dataPt++;
    void* is a pointer to an unknown value, so it illegal to increment as well as dereference it. The compiler does not know the size of what it points to, so it cannot know how many bytes to advance with ++.
    If you dereference a void* pointer, theoretically you would get void. But void is an illegal type that cannot be assigned to or from, so that compiler complains yet again.

    If I try to cast it Iīm informed that I should not attempt to cast a void pointer? I thought that was what they where good for.
    They are. Sort of.
    Just remember that there's no guarantee what you cast to is what it actually is. You have to be careful to make sure it's right.
    Last edited by Elysia; 02-07-2009 at 09:56 AM.
    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.

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    so essentially it stores an int**,
    actually UInt8**


    and there is no need to cast void pointer in C while assigning it to another pointer
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by vart View Post
    actually UInt8**
    Right. My mistake O_O

    and there is no need to cast void pointer in C while assigning it to another pointer
    But technically, you still get the same effect as when you cast it, so the result is the same.
    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.

  13. #13
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by Elysia View Post
    I don't know what exactly data & co are, but I do spot one problem.
    dataPt++;
    void* is a pointer to an unknown value, so it illegal to increment as well as dereference it. The compiler does not know the size of what it points to, so it cannot know how many bytes to advance with ++.
    If you dereference a void* pointer, theoretically you would get void. But void is an illegal type that cannot be assigned to or from, so that compiler complains yet again.
    So would using += 1 work instead of ++ in this example? I still canīt compile the version with the void pointer, so I went back to declaring the pointer UInt8, since Iīm not going to use it to point to anything else in this case. This still gives me a warning about incompatible pointer types for the assignement though. I have decided to ignore that for now however. Is the problem that I have allocated memory for what Iīm pointing to? I mean in this case itīs not really one byte worth of memory in total which the pointer might suggest?

    Quote Originally Posted by Elysia View Post
    They are. Sort of.
    Just remember that there's no guarantee what you cast to is what it actually is. You have to be careful to make sure it's right.
    Does this mean that dereferencing a void pointer always raise a compiler warning?

  14. #14
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    So would using += 1 work instead of ++ in this example?
    No, the pointer arithmetic does not work at all on the void pointer, because the size of the pointed object is unknown

    back to declaring the pointer UInt8
    pointer to UInt8 and pointer to pointer to UInt8 are different things

    I have decided to ignore that for now however
    Ignoring warnings that you do not understand is the easiest way to write a code that does absulutely different things from your intentions

    Is the problem that I have allocated memory for what Iīm pointing to?
    no
    Does this mean that dereferencing a void pointer always raise a compiler warning?
    you cannot dereference void pointer - so it will raise error not warning
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  15. #15
    Registered User
    Join Date
    Jan 2009
    Posts
    1,485
    Quote Originally Posted by vart View Post
    No, the pointer arithmetic does not work at all on the void pointer, because the size of the pointed object is unknown
    Hmm, ok. But at a first look it seems that explicitly adding one to whatever address the pointer contains should do what I want since what Iīm pointing to is a byte array.

    Quote Originally Posted by vart View Post
    pointer to UInt8 and pointer to pointer to UInt8 are different things
    Not exactly sure what you are saying here. Do you mean that the allocated memory essentially is a pointer to the first address of an array. If so how should I declare it.

    Quote Originally Posted by vart View Post
    Ignoring warnings that you do not understand is the easiest way to write a code that does absulutely different things from your intentions
    Yes I know, but I said 'for now' meaning until I have found a solution.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. dynamic allocation from 1 instead of zero
    By cfdprogrammer in forum C Programming
    Replies: 27
    Last Post: 04-28-2009, 08:21 AM
  2. pointer to array with dynamic allocation
    By cfdprogrammer in forum C Programming
    Replies: 22
    Last Post: 04-07-2009, 09:56 AM
  3. Dynamic memory allocation.
    By HAssan in forum C Programming
    Replies: 3
    Last Post: 09-07-2006, 05:04 PM
  4. Dynamic allocation (I thought it would crash)
    By Baaaah! in forum C Programming
    Replies: 16
    Last Post: 11-30-2005, 05:10 PM
  5. dynamic mem allocation prgm crash
    By rip1968 in forum C++ Programming
    Replies: 11
    Last Post: 05-10-2002, 05:09 PM