473,396 Members | 1,914 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Array capacity exceeded -- why does it still work?

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
  1. void create_array()
  2. {
  3.     /* Extracted numbers cannot exceed 8 digits */
  4.     #define MAX_DIGITS 8
  5.  
  6.     char  next_number[MAX_DIGITS];    /* temp buffer used to extract numbers */
  7.     int   index = 0;    /* stores the current position of 'next_number' */
  8.     int   iter;            /* traverses the string */
  9.  
  10.     num_count = 0;    /* stores the current position of 'series' */
  11.  
  12.     /* Traverse string extracting numbers */
  13.     for (iter = 0; iter <= strlen(string); iter++)
  14.     {
  15.         /* character is a digit */
  16.         if (string[iter] >= '0' && string[iter] <= '9')
  17.         {
  18.             /* Add digit to temp buffer */
  19.             next_number[index] = string[iter];
  20.             /* Update our position in the temp buffer */
  21.             index++;
  22.         }
  23.         /* charcter is a number delimiter (a non-digit immediately following a digit) */
  24.         else if (index > 0)
  25.         {
  26.             /* End the string */
  27.             next_number[index] = '\0';
  28.             /* Place number into array (converting to integer) */
  29.             series[num_count] = atoi(next_number);
  30.             /* Update position in number array ('series') */
  31.             num_count++;
  32.             /* Reset temp buffer */
  33.             index = 0;
  34.         }
  35.     }
  36.  
  37.     return;
  38. }
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 2271
willakawill
1,646 1GB
Can someone please explain why a 9-digit number can be placed into the 8 character array?

Thank you.
Hi, welcome to the wonderful world of DIY memory management.
The tradeoff for the speed you get using c++ is that you have to handle all possible problems yourself. This is a low level language without a safety net :)

When you dimension an array the OS will allocate a contiguous block of memory. Anything could be next in line to that block. You can still access the memory after your array and heaven help you if there is code there that your app is using and you overwrite it.

If I am using an array of 20 char.

char myarray[20];

Then the memory address for the first character is myarray[0]
If I use the expression myarray[1] I am asking the OS to go to the memory address which is 1 char (1 byte or 8 bits) further along. If my array was of type long it would be 4 bytes further along. So when I use something like myarray[22] which maybe from a mistake in a loop, I am asking the OS to look at the memory address which is 22 bytes further on. There is nothing in c++ to stop me from doing this and reading that memory address will not normally cause much of a problem. If I write to that address I could be causing app failure.
Dec 20 '06 #2
Banfa
9,065 Expert Mod 8TB
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
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
Banfa
9,065 Expert Mod 8TB
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
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
  1. /******************************************************************************
  2.  * create_array() -- Creates an array of numbers (series) by extracting the   *
  3.  *                   numerical values from a string of characters.            *
  4.  *                                                                            *
  5.  * [Preconditions]                                                            *
  6.  *                                                                            *
  7.  * string_ptr    --    String used to create the series (array) of values.    *
  8.  * string_len    --    Length of the string.                                  *
  9.  * series_ptr    --    The array to be created from the string.               *
  10.  *                                                                            *
  11.  * [Postconditions]                                                           *
  12.  *                                                                            *
  13.  * series_ptr    --    Series of extracted numerical values from string.      *
  14.  * count_ptr     --    Number of values in the series.                        *
  15.  ******************************************************************************/
  16. void create_array(char *str_ptr, int str_len, float *series_ptr, int *count_ptr)
  17. {
  18.     #define MAX_DIGITS 8                /* ignore numbers with more digits */
  19.  
  20.     char  next_number[MAX_DIGITS+1];    /* buffer used to extract numbers */
  21.     int   index = 0;                    /* stores buffer position */
  22.     int   str_iter;                     /* used to traverse string */
  23.     int   commit = TRUE;                /* used to ignore large numbers */
  24.     int   decimal_number = FALSE;       /* determines if number is decimal */
  25.  
  26.     /* Initially, there are no numbers in the series */
  27.     *count_ptr = 0;
  28.  
  29.     /* Traverse string extracting numeric values */
  30.     for (str_iter = 0; str_iter <= str_len; str_iter++)
  31.     {
  32.         /* Digit */
  33.         if (*(str_ptr + str_iter) >= '0' && *(str_ptr + str_iter) <= '9')
  34.         {
  35.             /* Ensure the array is not already full */
  36.             if (index < MAX_DIGITS)
  37.             {
  38.                 /* Append digit to array */
  39.                 next_number[index] = *(str_ptr + str_iter);
  40.                 /* Update buffer position */
  41.                 index++;
  42.             }
  43.             /* Overflow */
  44.             else
  45.             {
  46.                 /* Ignore the number */
  47.                 commit = FALSE;
  48.             }
  49.         }
  50.         /* Minus sign (-) */
  51.         else if (*(str_ptr + str_iter) == '-')
  52.         {
  53.             /* Check if a digit proceeds -> new negative number */
  54.             if (*(str_ptr + str_iter+1) >= '0' && *(str_ptr + str_iter+1) <= '9')
  55.             {
  56.                 /* If the buffer already contains a number commit it */
  57.                 if (index > 0)
  58.                 {
  59.                     /* Ensure buffer can be committed (i.e. no overflow) */
  60.                     if (commit == TRUE)
  61.                     {
  62.                         /* Mark the end of the number */
  63.                         next_number[index] = '\0';
  64.                         /* Add the next number to the series */
  65.                         *(series_ptr + *count_ptr) = atof(next_number);
  66.                         /* Update the series position */
  67.                         (*count_ptr)++;
  68.  
  69.                         /* Begin a new (negative) number */
  70.                         next_number[0] = '-';
  71.                         index = 1;
  72.  
  73.                         /* Reset decimal flag */
  74.                         decimal_number = FALSE;
  75.                     }
  76.                     /* Current buffer content previously overflowed */
  77.                     else
  78.                     {
  79.                         /* Begin a new (negative) number */
  80.                         next_number[0] = '-';
  81.                         index = 1;
  82.  
  83.                         /* Reset the 'commit' flag */
  84.                         commit = TRUE;
  85.                         /* Reset decimal flag */
  86.                         decimal_number = FALSE;
  87.                     }
  88.                 }
  89.                 /* Otherwise, begin a new (negative) number */
  90.                 else
  91.                 {
  92.                     /* Add a minus sign to the start of the buffer */
  93.                     next_number[0] = '-';
  94.                     /* Update buffer position */
  95.                     index = 1;
  96.                 }
  97.             }
  98.         }
  99.         /* Decimal */
  100.         else if (*(str_ptr + str_iter) == '.')
  101.         {
  102.             /* Ensure buffer is not empty and number hasn't overflowed */
  103.             if (index > 0 && commit == TRUE)
  104.             {
  105.                 /* If the character proceeding is not a digit -> delimiter */
  106.                 if (*(str_ptr + str_iter+1) < '0' || *(str_ptr + str_iter+1) > '9')
  107.                 {
  108.                     /* Mark the end of the number */
  109.                     next_number[index] = '\0';
  110.                     /* Add the number to the series */
  111.                     *(series_ptr + *count_ptr) = atof(next_number);
  112.  
  113.                     /* Update the series position */
  114.                     (*count_ptr)++;
  115.                     /* Reset the 'next number' position */
  116.                     index = 0;
  117.                     /* Reset decimal flag */
  118.                     decimal_number = FALSE;
  119.                 }
  120.                 /* If the buffer already contains a decimal -> delimeter */
  121.                 else if (decimal_number == TRUE)
  122.                 {
  123.                     /* Mark the end of the number */
  124.                     next_number[index] = '\0';
  125.                     /* Add the number to the series */
  126.                     *(series_ptr + *count_ptr) = atof(next_number);
  127.  
  128.                     /* Update the series position */
  129.                     (*count_ptr)++;
  130.                     /* Reset the 'next number' position */
  131.                     index = 0;
  132.                     /* Reset decimal flag */
  133.                     decimal_number = FALSE;
  134.                 }
  135.                 /* Ensure number doesn't overflow */
  136.                 else if (index < MAX_DIGITS-1)
  137.                 {
  138.                     /* Add decimal to buffer */
  139.                     next_number[index] = '.';
  140.                     /* Update buffer position */
  141.                     index++;
  142.                     /* Set 'decimal' flag*/
  143.                     decimal_number = TRUE;
  144.                 }
  145.                 /* Number overflowed */
  146.                 else
  147.                 {
  148.                     /* Ignore number */
  149.                     commit = FALSE;
  150.                     /* Reset decimal flag */
  151.                     decimal_number = FALSE;
  152.                 }
  153.             }
  154.         }
  155.         /* Number delimiter */
  156.         else if (index > 0)
  157.         {
  158.             /* Add number in buffer to series */
  159.             if (commit == TRUE)
  160.             {
  161.                 /* Mark the end of the number */
  162.                 next_number[index] = '\0';
  163.                 /* Add the next number to the series */
  164.                 *(series_ptr + *count_ptr) = atof(next_number);
  165.  
  166.                 /* Update the series position */
  167.                 (*count_ptr)++;
  168.                 /* Reset the 'next number' position */
  169.                 index = 0;
  170.                 /* Reset decimal flag */
  171.                 decimal_number = FALSE;
  172.             }
  173.             /* Number overflowed -- reset the buffer and flags */
  174.             else
  175.             {
  176.                 /* Reset the 'commit' flag */
  177.                 commit = TRUE;
  178.                 /* Reset the 'next number' position */
  179.                 index = 0;
  180.                 /* Reset decimal flag */
  181.                 decimal_number = FALSE;
  182.             }
  183.         }
  184.     }
  185.  
  186.     return;
  187. }
Dec 26 '06 #6

Sign in to post your reply or Sign up for a free account.

Similar topics

7
by: BrianJones | last post by:
In java, to work out the size of an array, say it was called a, you would do a.length which might return 10 as the number of elements. Is there a similar thing you can do in C++? I'd initially...
12
by: Eigenvector | last post by:
I've been dinking around with this code for a while now and I can't seem to figure out where the problem lies. The original problem was that I for some reason or another couldn't allocate few...
4
by: emma middlebrook | last post by:
Hi Straight to the point - I don't understand why System.Array derives from IList (given the methods/properties actually on IList). When designing an interface you specify a contract. Deriving...
4
by: Peter | last post by:
I run into this situation all the time and I'm wondering what is the most efficient way to handle this issue: I'll be pulling data out of a data source and want to load the data into an array so...
19
by: Tom Jastrzebski | last post by:
Hello, I was just testing VB.Net on Framework.Net 2.0 performance when I run into the this problem. This trivial code attached below executed hundreds, if not thousand times faster in VB 6.0...
10
by: Russell Mangel | last post by:
I have written the following program using VS2005. The program is a Dynamic Array similar to System.Collections.ArrayList in .NET. The program works okay until I reach 65536, I can't seem to figure...
23
by: sandy | last post by:
I need (okay, I want) to make a dynamic array of my class 'Directory', within my class Directory (Can you already smell disaster?) Each Directory can have subdirectories so I thought to put these...
14
by: ptq2238 | last post by:
Hi, I'm getting confused with arrays and hope someone can shed light on my code. I wrote this to try and learn about files and arrays as I thought if I could grab each element and place them into...
35
by: Lee Crabtree | last post by:
This seems inconsistent and more than a little bizarre. Array.Clear sets all elements of the array to their default values (0, null, whatever), whereas List<>.Clear removes all items from the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.