Thread: Arrays out-of-bounds in functions only?

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    42

    Arrays out-of-bounds in functions only?

    Is it bad practice (and programming) to use plain arrays in functions not unlike this?
    Code:
    char function(char *string)
    {
      char a[4]; /* Is this bad? */
      /* etc... */
      return a[whatever];
    }
    I've done that before and have gotten really severe out of bounds (when the 2nd or 3rd call of the array came around), like -107839 or something for int arrays, -84 for char arrays, etc. I solved the problem like this:
    Code:
    /* Instead of this: */
    char a[4];
    /* I used: */
    char *a = calloc(4, sizeof(char));
    But why doesn't my declaration of my char array 'a' work?
    Sigh, nothing ever works the first try.

    Register Linux User #314127

  2. #2
    Greetings KneeLess,

    Declaring local variables in function(s) is not "bad". It's actually done alot in programming techniques.

    Uninitialized Variables
    · These are generally the function flows in codes that might result in an uninitialized variable to be used in the function from whom some other data member accepts data. As the variable from whom data is accepted is uninitialized it's content are junk values, that causes an unpredictable outcome.

    Out Of Bound Access
    · These are cases where the code accesses an array index that exceeds its upper or lower limit and reads or writes to that particular address. This might cause an improper value to be fetched or may result in overwriting of other members in the function the results of which might be disastrous.

    To sum it up if you try to view or access uninitialized variables, it will probably show junk. We could think of it as terms where the variable doesnt contain any data, but the variable does exist and holds some type of data.

    Array subscripts always start at zero in C, so the elements of your example are a[0], a[1], a[2], and a[3]. If you take the number 4, start at 0 and count to 4 you get 3; thus the maximum locations of your existing elements.

    If you did make a function for example return a character or number using an array, it would not be difficult as long as you return a valid and initialized index. For example:
    Code:
    char myLetter(int l) {
    	char a[4] = {'a', 'b', 'c', 'd'};
    
    	if (l > 3)
    		return 0;
    
    	return a[l];
    }
    Example 1.1: Returning a variable.

    This function works as the following:
    Code:
    take one parameter
    	initialize an array with filled indices
    	check if the parameter exceeds the arrays boundaries
    return the index's value
    Instruction 1.1: How our example works.

    If you have further questions, please feel free to ask.


    - Stack Overflow
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    KneeLess > The code you posted is correct. I'm guessing where your problem arises is when you have something like:

    Code:
    char* function(char *string)
    {
      char a[4]; 
      /* etc... */
      return a;
    }
    The above code will give you problems when you try and dereference the returned pointer in the calling function. The correct way to get around this is to dynamically allocate memory using calloc or malloc as you did in your second code snippet.

  4. #4
    Registered User
    Join Date
    Aug 2003
    Posts
    42
    StackOverflow, thanks for the nice tutorial, but I'm positive I didn't overflow my boundries. Plus wouldn't allocating calloc to give me 4 chars overflow it the same if I changed nothing else?
    The above code will give you problems when you try and dereference the returned pointer in the calling function. The correct way to get around this is to dynamically allocate memory using calloc or malloc as you did in your second code snippet.
    I guess it's time for the real code. It finds flush draws in poker hands (I've snipped some):
    Code:
    int havefdraw(char *cards)
    {
            int a[4];
            register int x = 0, high = 0;
            for(x = 0; x < strlen(cards); x++)
            {
                    if(x % 2)
                    {
                            if(cards[x] == 'h')
    			{
                                    a[0]++;
    				printf("It's a heart, a[0]: %d\n",a[0]);
    			}
                            /* Snip */
                    }
            }
            /* Snip, but return something, etc, it's irrelevant */
    }
    The first time this runs through it's fine, the second time it prints:

    It's a heart, a[0]: -107847

    As many times as there is a heart. I'm thinking that somehow, only the second time (or 3rd, 4th, etc.) it overstepped it's boundries or is using other memory. Is this the fault of the compiler?
    Sigh, nothing ever works the first try.

    Register Linux User #314127

  5. #5
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >a[0]++;
    What value is in a[0] at this point? Because the array is a local variable, its contents are uninitialized until you give them a value.
    My best code is written with the delete key.

  6. #6
    Agreed,

    The array did not exceed out of bounds, though you are trying to increment a variable that has not been initialized. For examlpe:
    Code:
    int i;
    So far the variable i has not been initialized, though it has been declared. There is a difference. The declaration of a variable creates its existance within the program or function. The initialization of a variable defines what it is / the value.

    So far you are just declaring the integer array, not initializing it. You could initialize each index of the array or just use {0} to initialize all indices to zero:
    Code:
    int a[5] = {0};
    Here are some useful tips:

    • The initializer for an array is a brace-enclosed list of initializers for its members.
    • If the array has unknown size, the number of initializers determines the size of the array, and its type becomes complete.
    • If the array has a fixed size, the number of initializers may not exceed the number of members of the array; if there are fewer, the trailing members are initialized with 0.

    That's why we initialize the first index to 0, allowing the trailing indices initialize to 0. If you have further questions, please feel free to ask.


    - Stack Overflow
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. functions using arrays
    By trprince in forum C Programming
    Replies: 30
    Last Post: 11-17-2007, 06:10 PM
  2. Passing arrays of pointers into functions
    By ashley in forum C Programming
    Replies: 5
    Last Post: 01-13-2007, 06:48 PM
  3. storage class, arrays, functions and good layout
    By disruptivetech in forum C Programming
    Replies: 4
    Last Post: 12-02-2005, 02:34 PM
  4. functions and arrays
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 03-14-2002, 09:57 AM
  5. elements of arrays; functions
    By sballew in forum C Programming
    Replies: 6
    Last Post: 09-03-2001, 01:48 AM