Thread: error: redefinition of

  1. #1
    Registered User
    Join Date
    Mar 2015
    Posts
    9

    Question error: redefinition of

    I am trying to make a short mwe of realloc, more specifically how it can be used to expand integer arrays. Unfortunately due to the error:
    Code:
    a@a-TP-X200:/media/a/LG/AC/Learn/Programming/C/arrays$ clang -g -std=c99 -Wall -Wvla -Werror -fsanitize=address,undefined realloc_appendElements_func4.c 
    In file included from realloc_appendElements_func4.c:5:
    ./verif_HeapMemRemains.h:2:7: error: redefinition of 'verif_HeapMemRemains'
            void verif_HeapMemRemains(int * buffer)
                 ^
    ./verif_HeapMemRemains.h:2:7: note: previous definition is here
            void verif_HeapMemRemains(int * buffer)
                 ^
    1 error generated.
    I prefer header files because:
    Organization:
    For future programs that use same/similar functions, I can look up past programs WAY QUICKER than pondering for hour after hour on remembering that I put the function for scanning in an integer Array in a program designed to demonstrate how to use 'remalloc'" or a program designed to track how many segments in a millipede's body with age or whatever.
    and don't care whether it is reusable or not.

    My program:
    realloc_appendElements_func4.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "printInt.h"
    #include "expandArrThenVerif_int.h"
    #include "verif_HeapMemRemains.h"
    #include "scanIntArr.h"
    
    //PURPOSE
    //    First allocate enough for just a few first numbers.  Then to demonstrate "realloc"'s ability to resize an already existing array take in more numbers to add to the new space.
    
    //Main Program
        int main (int argc, char** argv)
        {
            int * buffer;
    
            //1ST ARRAY
                int currentSize = 0;
                int increaseSize = 3;
                int firstElemOfNewAnnex = currentSize;
                currentSize += increaseSize;
    
                //Integer Array 1:  Allocate enough memory for 10 integers
                    buffer = (int *) malloc (currentSize*sizeof(int));
    
                //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
                    verif_HeapMemRemains(buffer);
    
                //Scan in new values for the buffer
                    scanIntArr(buffer, firstElemOfNewAnnex, currentSize);
    
                //DEBUG
                    printInt(buffer, currentSize);
                
                
            //Expand Array
                char decide;
                
            //User decides to append array
                printf("Add elements(Y) or quit(N)> ");
    
                while((decide = getchar()) != EOF)
                {
                    //Get rid of ensuing line feed
                        getchar();
                        
                    //Upon user input 'n' terminate loop
                        if(decide == 'n' || decide == 'N')
                        {
                            break;
                        }
    
                    //Number of elements to add to current array
                        printf("Enter quantity of elements to add to end of current array> ");
                        
                        //Verify scan function succeeded scanning Data
                            if((scanf("%d", &increaseSize)) != 1)
                            {
                                perror("scanf didn't return \"1\"/n");
                                //printf("%d/n", stdin);
                                exit(EXIT_FAILURE);
                            }
                        
                        ////Get rid of ensuing line feed
                            //getchar();
    
                    //Record which element new space will begin on
                            firstElemOfNewAnnex = currentSize;
                            currentSize += increaseSize;
    
                    //REALLOC CURRENT BUFFER, VERIFY HEAP HAD ENOUGH REMAINING MEM
                        buffer = expandArrThenVerif_int(buffer, currentSize);
    
                    //Scan in second set of values for the buffer
                        scanIntArr(buffer, firstElemOfNewAnnex, currentSize);
    
                    //DEBUG
                        printInt(buffer, currentSize);
    
                    //User decides to append array
                        printf("Add elements(Y) or quit(N)> ");
                }
    
            free (buffer);
    
            return 0;
        }
    verif_HeapMemRemains.h
    Code:
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
    void verif_HeapMemRemains(int * buffer)
    {
        //Check if heap had enough memory to allocate above space (out of memory)
            if (buffer==NULL)
            {
                printf("Error allocating memory!");
                
                //Free the initial memory block.
                    free (buffer);
                    
                exit (EXIT_FAILURE);
            }
    }
    scanIntArr.h
    Code:
    //SCAN IN VALUES TO THE ARRAY
    void scanIntArr(int * buffer, int s, int l)
    {
        int i;
    
    //Initialize "buffer's" values
        for(i = 0 + s; i < l; i++)
        {
            printf("Enter integer array's %d 's element> ", i);
            scanf("%d", &buffer[i]);
        }
    }
    expandArrThenVerif_int.h
    Code:
    #ifndef verif_HeapMemRemains
    #include "verif_HeapMemRemains.h"
    #endif
    
    //REALLOC CURRENT BUFFER, VERIFY HEAP HAD ENOUGH REMAINING MEMORY
        int * expandArrThenVerif_int(int * buffer, int currentSize)
        {
            /*get more memory with realloc*/
                //Assign pointer to the newly allocated memory to current variable "buffer"
                    buffer = (int*) realloc(buffer, (currentSize)*sizeof(int));
                        //***
    
            //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
                verif_HeapMemRemains(buffer);
    
            return(buffer);
        }
    Please notice how in expandArrThenVerif_int.h I've attempted to use a header file. Even though it is realitively easy to find a lot of tutorials on how to understand the "theory" of header files, I couldn't find any concrete real life examples. Any recommendations?

    Optionally, before I moved the functions outside of the main program, the decide = getchar() clause fails (can see when running in GDB) and no way to terminate loop, but that is not the main question, and I can repost for website organization standards if venerable contributors think appropriate.
    Attached Files Attached Files

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I prefer header files because:
    Except - it doesn't work!

    Putting source code in header files is a bad idea.

    If you really want code re-use then do this.
    Code:
    // verif_HeapMemRemains.h
    
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
    void verif_HeapMemRemains(int * buffer);
    Code:
    // verif_HeapMemRemains.c
    #include "verif_HeapMemRemains.h"
    
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
    void verif_HeapMemRemains(int * buffer)
    {
        //Check if heap had enough memory to allocate above space (out of memory)
            if (buffer==NULL)
            {
                printf("Error allocating memory!");
                
                //Free the initial memory block.
                    free (buffer);
                    
                exit (EXIT_FAILURE);
            }
    }
    If you then want to create a set of functions you want to re-use, then put them all into a library.

    Code:
    gcc -c something.c   # for all your re-usable source
    ar c libmytools.a something.o # list all the other .o files
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Also, getchar() returns an int, not char, so decide should be an int, not char. (On some platforms, char is unsigned, so it can't ever be equal to EOF. Plus, it's easier to do the correct thing--you can just type 3 letters (int) instead of 4 (char).)

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Quote Originally Posted by christop View Post
    Also, getchar() returns an int, not char, so decide should be an int, not char. (On some platforms, char is unsigned, so it can't ever be equal to EOF.
    That's not the actual reason getchar returns an int. The reason is so that EOF can be chosen to be a bit pattern that can never occur in a char (an "out-of-band" value). Obviously that means it must have more bits and have at least one of those extra bits set. As EOF is defined to be negative, it's highest bit will be set for sure. That is enough to distinguish it from any 8-bit value. It is usually set to -1 (all bits set for 2's complement).
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Yes, I know. I just wanted to point out one problem that's caused by storing the return value of getchar() in a char instead of int.

    Another problem is that, on platforms where char is signed (so that decide can be equal to EOF), it's still broken. It means the program can't tell the difference between actual data which has the value 0xFF and end-of-file.

    Whether char is signed or unsigned, it's wrong to store the return value of getchar() in a char variable.

  6. #6
    Registered User
    Join Date
    Mar 2015
    Posts
    9

    Red face new concept

    Quote Originally Posted by Salem View Post
    Putting source code in header files is a bad idea.

    If you really want code re-use then do this.
    Code:
    // verif_HeapMemRemains.h
    
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
    void verif_HeapMemRemains(int * buffer);
    Code:
    // verif_HeapMemRemains.c
    #include "verif_HeapMemRemains.h"
    
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
    void verif_HeapMemRemains(int * buffer)
    {
        //Check if heap had enough memory to allocate above space (out of memory)
            if (buffer==NULL)
            {
                printf("Error allocating memory!");
                
                //Free the initial memory block.
                    free (buffer);
                    
                exit (EXIT_FAILURE);
            }
    }
    Ohhh. I never did anything like this before, guess I really was clueless. Time to sail on into uncharted waters.

    The vital lessons I learned from this above advice is:

    1) Making programs with multiple *.c files exists.
    ** Originally I thought that one program could only have one *.c file and multiple *.h files, this stems from me maybe misunderstanding one of the header file tutorials that I encountered before online. **

    2) When encountering programs that are too long, you MAY organize by moving functions into separate files ending in *.c, and for the function declarations those are the things that should be placed in the *.h files.

    3) *.c files' theme is code source files, not just the main program.


    I checked back in K & R, and it does mention a program with multiple source files and only one header file, but Chapter 4.5 Header Files is really quite brief.

    Luckily with your advice I just found flavio's header File tutorial where he explained the basic concept.

    Actually 're-using' the code would be nice!

    Thanks a lot!
    Last edited by andrew.comly; 06-12-2020 at 08:29 PM. Reason: spacing, readability

  7. #7
    Registered User
    Join Date
    Mar 2015
    Posts
    9

    1) Corrections of header file misconception; 2) Entailing getchar() input Error

    After implementing the above principles, I have the following program:
    realloc_appendElements_func4.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "realloc_appendElem.h"
    
    
    //PURPOSE
    //    First allocate enough for just a few first numbers.  Then to demonstrate "realloc"'s ability to resize an already existing array take in more numbers to add to the new space.
    
    //Main Program
        int main (int argc, char** argv)
        {
            int * buffer;
    
            //1ST ARRAY
                int currentSize = 0;
                int increaseSize = 3;
                int firstElemOfNewAnnex = currentSize;
                currentSize += increaseSize;
    
                //Integer Array 1:  Allocate enough memory for 10 integers
                    buffer = (int *) malloc (currentSize*sizeof(int));
    
                //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
                    verif_HeapMemRemains(buffer);
    
                //Scan in new values for the buffer
                    scanIntArr(buffer, firstElemOfNewAnnex, currentSize);
    
                //DEBUG
                    printInt(buffer, currentSize);
                
                
            //Expand Array
                int decide;            //If you declare as 'char', then the entailing while loop will not be able to pick up 'n/N' as entered by user, thus will continue forever.
                
            //User decides to append array
                printf("Add elements(Y) or quit(N)> ");
    
                while((decide = getchar()) != EOF)
                {
                    //Display user's decision
                        printf("You just entered %c\n", decide);
    
                    //Get rid of ensuing line feed
                        getchar();
                        
                    //Upon user input 'n' terminate loop
                        if(decide == 'n' || decide == 'N')
                        {
                            break;
                        }
    
                    //Number of elements to add to current array
                        printf("Enter quantity of elements to add to end of current array> ");
                        
                        //Verify scan function succeeded scanning Data
                            if((scanf("%d", &increaseSize)) != 1)
                            {
                                perror("scanf didn't return \"1\"/n");
                                //printf("%d/n", stdin);
                                exit(EXIT_FAILURE);
                            }
                        
                        ////Get rid of ensuing line feed
                            //getchar();
    
                    //Record which element new space will begin on
                            firstElemOfNewAnnex = currentSize;
                            currentSize += increaseSize;
    
                    //REALLOC CURRENT BUFFER, VERIFY HEAP HAD ENOUGH REMAINING MEM
                        buffer = expandArrThenVerif_int(buffer, currentSize);
    
                    //Scan in second set of values for the buffer
                        scanIntArr(buffer, firstElemOfNewAnnex, currentSize);
    
                    //DEBUG
                        printInt(buffer, currentSize);
    
                    //User decides to append array
                        printf("Add elements(Y) or quit(N)> ");
                }
    
            free (buffer);
    
            return 0;
        }
    realloc_appendElem.h
    Code:
    int * expandArrThenVerif_int(int *, int);
    void scanIntArr(int *, int, int);
    void verif_HeapMemRemains(int *);
    void printInt(int * , int);
    expandArrThenVerif_int.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "realloc_appendElem.h"
    
    
    //REALLOC CURRENT BUFFER, VERIFY HEAP HAD ENOUGH REMAINING MEMORY
        int * expandArrThenVerif_int(int * buffer, int currentSize)
        {
            /*get more memory with realloc*/
                //Assign pointer to the newly allocated memory to current variable "buffer"
                    buffer = (int*) realloc(buffer, (currentSize)*sizeof(int));
                        //***
    
            //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
                verif_HeapMemRemains(buffer);
    
            return(buffer);
        }
    scanIntArr.c
    Code:
    #include <stdio.h>
    
    //SCAN IN VALUES TO THE ARRAY
        void scanIntArr(int * buffer, int s, int l)
        {
            int i;
    
        //Initialize "buffer's" values
            for(i = 0 + s; i < l; i++)
            {
                printf("Enter integer array's %d 's element> ", i);
                scanf("%d", &buffer[i]);
            }
        }
    verif_HeapMemRemains.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    //VERIFY NEW MEMORY SUCCESSFULLY ALLOCATED
        void verif_HeapMemRemains(int * buffer)
        {
            //Check if heap had enough memory to allocate above space (out of memory)
                if (buffer==NULL)
                {
                    printf("Error allocating memory!");
                    
                    //Free the initial memory block.
                        free (buffer);
                        
                    exit (EXIT_FAILURE);
                }
        }
    printInt.c
    Code:
    #include <stdio.h>
    
    void printInt(int* arr, int l)
    {
        int i;
        for(i=0; i < l; i++)
        {
            printf("\t\"%d\".\n", arr[i]);
        }
    }
    Even though now the above program compiles with
    Code:
    $ clang -g -std=c99 -Wall -Wvla -Werror -fsanitize=address,undefined realloc_appendElements_func4.c expandArrThenVerif_int.c scanIntArr.c verif_HeapMemRemains.c printInt.c
    so I have made significant progress thanks to Salem, christop and john.c vital corrections, thanks a lot!


    Entailing Question
    However the user input part for decision is still screwed up, with the following runtime error:
    Code:
    a@a-TP-X200:/media/a/LG/AC/Learn/Programming/C/arrays/reallocProject$ ./a.outEnter integer array's 0 's element> 0
    Enter integer array's 1 's element> 1
    Enter integer array's 2 's element> 2
        "0".
        "1".
        "2".
    Add elements(Y) or quit(N)> You just entered 
    <<Not until here does the program wait until I can enter code!!!>>>
    My target behavior for the program is to ask "Add elements(Y) or quit(N)>", and then at that point GIVE ME A CHANCE TO ANSWER. But when I want it to give me a chance to answer it jumps ahead and prints the data confirmation line:
    Code:
        //Display user's decision
            printf("You just entered %c\n", decide);".
    I had previously said
    no way to terminate loop, but that is not the main question, and I can repost for website organization standards if venerable contributors think appropriate.
    so I can repost this question if someone tells me to or doesn't answer, but the entailing question is:

    How to get the program not to jump??
    Last edited by andrew.comly; 06-14-2020 at 08:25 PM. Reason: clarity

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > //Get rid of ensuing line feed
    You also need this after your %d scanf as well.

    Otherwise the getchar() on the next loop iteration just comes right back with a return character.

    Mixing getchar() with scanf is always problematic.

    Not to mention later on, separating out I/O errors from conversion errors when using just simple scanf calls.

    In short, always use fgets() to read a line into a buffer, then use whatever you like (sscanf, str..., etc) to extract info from the buffer.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Mar 2015
    Posts
    9

    Red face non-concise solution

    I found the error. First off, I already knew whenever one uses getchar() to read in a int/char, that you have to use another entailing getchar() to shoo off the wretchedly ensuing new line (ASCII 10). So I uncommented the originally wrongly commented out getchar() after the perror codeblock.

    I tried again but the problem then eventually resurfaced at a later segment. Then it suddenly dawned on me, even after using scanf the impish newline will befoul stdin, so I then added
    Code:
                        //Get rid of ensuing line feed
                            getchar();
    subsequent to any functions that used scanf. I ran it again and no more runtime/semantic errors. But I then examined the scanIntArr function and found:
    Code:
    scanf("%d", &buffer[i]);
    1. scanf"%d" --> scanf"%d\n" ??
    I modified it with a "%d\n" along with getting rid of the getchar() subsequent to the scanIntArr function calls, and that produced the following runtime error:
    Code:
    $ ./a.outEnter integer array's 0 's element> 0
    1
    Enter integer array's 1 's element> 2
    Anotherwords, with the "%d\n" rather than "%d", the for loop doesn't iterate forward properly.
    fail

    2. scanf"%d" --> scanf"%d " ??
    I then tried:
    Code:
    scanf("%d ", &buffer[i]);
    which produced:
    Code:
    Enter integer array's 0 's element> 0
    1
    Enter integer array's 1 's element> 2
    Enter integer array's 2 's element> 3
        "0".
        "1".
        "2".
    Add elements(Y) or quit(N)> You just entered 3
    Enter quantity of elements to add to end of current array>
    "%d "'s two errors:
    1) First iteration delayed
    2) After program run still needed a getchar() to dispel the doggedly impish 'newline'.
    fail


    So with "%d\n" and "%d " both failed, I guess one must amass oodles of:
    Code:
                        //Get rid of ensuing line feed
                            getchar();
    In case anyone knows a way to more be concise[circumvent the need for so many getchar()], please inform me.
    Last edited by andrew.comly; 06-14-2020 at 11:48 PM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by andrew.comly
    In case anyone knows a way to more be concise[circumvent the need for so many getchar()], please inform me.
    Salem already shared the "secret" with you in the previous post:
    Quote Originally Posted by Salem
    In short, always use fgets() to read a line into a buffer, then use whatever you like (sscanf, str..., etc) to extract info from the buffer.
    (Of course, where appropriate you can replace fgets with another function that reads a line, e.g., POSIX getline)
    Last edited by laserlight; 06-15-2020 at 12:39 AM.
    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

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    The problem is, "%d\n" doesn't mean an integer followed by a newline, it means an integer, followed by any continuous sequence of white-space characters (spaces, tabs, newlines, formfeeds).

    As such, it won't actually return until there is a non-space on the input stream.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 10-29-2012, 03:33 AM
  2. Replies: 1
    Last Post: 11-15-2010, 11:14 AM
  3. variable redefinition error
    By 7smurfs in forum C++ Programming
    Replies: 4
    Last Post: 12-14-2004, 05:55 PM
  4. Redefinition Error
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 05-04-2002, 04:11 PM

Tags for this Thread