458,135 Members | 1,280 Online Need help? Post your question and get tips & solutions from a community of 458,135 IT Pros & Developers. It's quick & easy.

# Array capacity exceeded -- why does it still work?

 P: 5 I am having difficulty understanding why the following code does not result in error. The code below simply traverses a string, extracting any continuous sequence of digits (0 - 9) and placing them into a separate array. For example, the following string: abc1&qwerty22.xyz0321ijk5Q_ #*9 should produce the array: [1, 22, 321, 5, 9]. Given the array declaration char next_number[MAX_DIGITS], where MAX_DIGITS is defined to be 8, the number of consecutive digits that can be placed in the array is limited to 8. However, when testing this code with the 9-digit number '123456789', it appears that this number is placed into the 8 character array without raising any exceptions. I would have expected that such a test to break the program, but it didn't. Further, when printing out the array of numbers, the number '123456789' is printed correctly; in other words, it was successfully stored somehow before being transferred to the array of numbers. Can someone please explain why a 9-digit number can be placed into the 8 character array? Thank you. Expand|Select|Wrap|Line Numbers void create_array() {     /* Extracted numbers cannot exceed 8 digits */     #define MAX_DIGITS 8       char  next_number[MAX_DIGITS];    /* temp buffer used to extract numbers */     int   index = 0;    /* stores the current position of 'next_number' */     int   iter;            /* traverses the string */       num_count = 0;    /* stores the current position of 'series' */       /* Traverse string extracting numbers */     for (iter = 0; iter <= strlen(string); iter++)     {         /* character is a digit */         if (string[iter] >= '0' && string[iter] <= '9')         {             /* Add digit to temp buffer */             next_number[index] = string[iter];             /* Update our position in the temp buffer */             index++;         }         /* charcter is a number delimiter (a non-digit immediately following a digit) */         else if (index > 0)         {             /* End the string */             next_number[index] = '\0';             /* Place number into array (converting to integer) */             series[num_count] = atoi(next_number);             /* Update position in number array ('series') */             num_count++;             /* Reset temp buffer */             index = 0;         }     }       return; } Note: 'string' and 'series' are global variables. I know they should be parsed as parameters (using pointers/references), but it has been a while since I have touched on these topics... I am slowly relearning the C language :-) Dec 20 '06 #1
5 Replies

 Expert Mod 5K+ P: 8,950 Specifically writing outside the bounds of an array in C/C++ produces undefined behaviour (which is a specified type of behaviour). Undefined behaviour is, surprisingly, not defined as anything. A program exhibiting undefined behaviour may 1. Work as expected 2. Fail with an error logically consistent with the error (i.e. procude an out of bounds memoary access exception). 3. Do anything else you can think of, for example format the harddisk. You should avoid undefined behaviour, it is BAD. The problem you have come accross is that sometimes 1 happens which can result in you not noticing the error in the code. However since the behaviour is undefined the same code may produce radically different result on different systems. The are tools out there to help track this sort of thing, static analysis tools such as Purify or splint. Dec 20 '06 #3

 P: 27 actually u should compare the value of 'iter' itself not array[iter] u dont bother about whats inside it as long as u made ur validations before Dec 20 '06 #4

 Expert Mod 5K+ P: 8,950 actually u should compare the value of 'iter' itself not array[iter] u dont bother about whats inside it as long as u made ur validations before I do not think you have read the problem and code correctly, I can not see how this comment applies to the posted problem. Dec 20 '06 #5

 P: 5 Thank you... it's all beginning to come back to me :-) For completeness, here is my corrected code. For those of you who are more senior programmers, I would very much appreciate feedback with regards to my programming style and choice of implementation. How would have you done things different? Expand|Select|Wrap|Line Numbers /******************************************************************************  * create_array() -- Creates an array of numbers (series) by extracting the   *  *                   numerical values from a string of characters.            *  *                                                                            *  * [Preconditions]                                                            *  *                                                                            *  * string_ptr    --    String used to create the series (array) of values.    *  * string_len    --    Length of the string.                                  *  * series_ptr    --    The array to be created from the string.               *  *                                                                            *  * [Postconditions]                                                           *  *                                                                            *  * series_ptr    --    Series of extracted numerical values from string.      *  * count_ptr     --    Number of values in the series.                        *  ******************************************************************************/ void create_array(char *str_ptr, int str_len, float *series_ptr, int *count_ptr) {     #define MAX_DIGITS 8                /* ignore numbers with more digits */       char  next_number[MAX_DIGITS+1];    /* buffer used to extract numbers */     int   index = 0;                    /* stores buffer position */     int   str_iter;                     /* used to traverse string */     int   commit = TRUE;                /* used to ignore large numbers */     int   decimal_number = FALSE;       /* determines if number is decimal */       /* Initially, there are no numbers in the series */     *count_ptr = 0;       /* Traverse string extracting numeric values */     for (str_iter = 0; str_iter <= str_len; str_iter++)     {         /* Digit */         if (*(str_ptr + str_iter) >= '0' && *(str_ptr + str_iter) <= '9')         {             /* Ensure the array is not already full */             if (index < MAX_DIGITS)             {                 /* Append digit to array */                 next_number[index] = *(str_ptr + str_iter);                 /* Update buffer position */                 index++;             }             /* Overflow */             else             {                 /* Ignore the number */                 commit = FALSE;             }         }         /* Minus sign (-) */         else if (*(str_ptr + str_iter) == '-')         {             /* Check if a digit proceeds -> new negative number */             if (*(str_ptr + str_iter+1) >= '0' && *(str_ptr + str_iter+1) <= '9')             {                 /* If the buffer already contains a number commit it */                 if (index > 0)                 {                     /* Ensure buffer can be committed (i.e. no overflow) */                     if (commit == TRUE)                     {                         /* Mark the end of the number */                         next_number[index] = '\0';                         /* Add the next number to the series */                         *(series_ptr + *count_ptr) = atof(next_number);                         /* Update the series position */                         (*count_ptr)++;                           /* Begin a new (negative) number */                         next_number = '-';                         index = 1;                           /* Reset decimal flag */                         decimal_number = FALSE;                     }                     /* Current buffer content previously overflowed */                     else                     {                         /* Begin a new (negative) number */                         next_number = '-';                         index = 1;                           /* Reset the 'commit' flag */                         commit = TRUE;                         /* Reset decimal flag */                         decimal_number = FALSE;                     }                 }                 /* Otherwise, begin a new (negative) number */                 else                 {                     /* Add a minus sign to the start of the buffer */                     next_number = '-';                     /* Update buffer position */                     index = 1;                 }             }         }         /* Decimal */         else if (*(str_ptr + str_iter) == '.')         {             /* Ensure buffer is not empty and number hasn't overflowed */             if (index > 0 && commit == TRUE)             {                 /* If the character proceeding is not a digit -> delimiter */                 if (*(str_ptr + str_iter+1) < '0' || *(str_ptr + str_iter+1) > '9')                 {                     /* Mark the end of the number */                     next_number[index] = '\0';                     /* Add the number to the series */                     *(series_ptr + *count_ptr) = atof(next_number);                       /* Update the series position */                     (*count_ptr)++;                     /* Reset the 'next number' position */                     index = 0;                     /* Reset decimal flag */                     decimal_number = FALSE;                 }                 /* If the buffer already contains a decimal -> delimeter */                 else if (decimal_number == TRUE)                 {                     /* Mark the end of the number */                     next_number[index] = '\0';                     /* Add the number to the series */                     *(series_ptr + *count_ptr) = atof(next_number);                       /* Update the series position */                     (*count_ptr)++;                     /* Reset the 'next number' position */                     index = 0;                     /* Reset decimal flag */                     decimal_number = FALSE;                 }                 /* Ensure number doesn't overflow */                 else if (index < MAX_DIGITS-1)                 {                     /* Add decimal to buffer */                     next_number[index] = '.';                     /* Update buffer position */                     index++;                     /* Set 'decimal' flag*/                     decimal_number = TRUE;                 }                 /* Number overflowed */                 else                 {                     /* Ignore number */                     commit = FALSE;                     /* Reset decimal flag */                     decimal_number = FALSE;                 }             }         }         /* Number delimiter */         else if (index > 0)         {             /* Add number in buffer to series */             if (commit == TRUE)             {                 /* Mark the end of the number */                 next_number[index] = '\0';                 /* Add the next number to the series */                 *(series_ptr + *count_ptr) = atof(next_number);                   /* Update the series position */                 (*count_ptr)++;                 /* Reset the 'next number' position */                 index = 0;                 /* Reset decimal flag */                 decimal_number = FALSE;             }             /* Number overflowed -- reset the buffer and flags */             else             {                 /* Reset the 'commit' flag */                 commit = TRUE;                 /* Reset the 'next number' position */                 index = 0;                 /* Reset decimal flag */                 decimal_number = FALSE;             }         }     }       return; } Dec 26 '06 #6 