Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. The Unforeseen Problem

The Unforeseen Problem

Scheduled Pinned Locked Moved Clever Code
helpgraphicsregex
15 Posts 8 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B benjymous

    Wouldn't that be caught if the warning level was at 4?

    J Offline
    J Offline
    John R Shaw
    wrote on last edited by
    #6

    Actually no, because it was written for Windows 3.1 using the VC/C++ 1.52; when I received the code I compiled it at the highest level and only received 7 warnings. The number of serious errors I found took several months to fix, by the time I was finished I believed if it so much as burped I could tell you where the problem was.

    INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra

    1 Reply Last reply
    0
    • W Warren Stevens

      John R. Shaw wrote:

      The equation on the right-hand side consists of an unsigned character (8-bit integer) and an unsigned short (16-bit integer), which means that the result will be an unsigned short value. The left-hand side of the equation is an unsigned long (32-bit integer)

      I know this is 1995 code, but I would hope that no one is using 8-bit or 16-bit integer types when writing any new code (in the age of $1/GB hard disks) :sigh: I'm also not a fan of unsigned types. With the conversion of -1 to a huge number (who thought allowing that conversion was a good idea ?!?) they're more trouble than they're worth. The moral of the story is: "use int for all integer data".


      www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

      J Offline
      J Offline
      John R Shaw
      wrote on last edited by
      #7

      Warren Stevens wrote:

      The moral of the story is: "use int for all integer data".

      Even now you should use the types that are required and if an int had been used instead of unsigned values the program would have crashed a long time ago. The 8-bit value is an unsigned char value, in a string of character codes. The 16-bit value, an unsigned int (back then), is actually a global that was set before this function was called and its type could not be changed without affecting other parts of the program. Remember I did not design the original code; it was just my job to fix it and then maintain it there after. Try the following to see what happens when the degree symbol is converted, without first converting it to unsigned char:

      char str[5] = “22°C”;
      int c1 = str[0];
      int c2 = str[1];
      int c3 = str[3];
      int c4 = str[4];

      Note that the same conversion is required before passing the character to any of the character clasification funcions; like isdigit(int).

      INTP "Program testing can be used to show the presence of bugs, but never to show their absence."Edsger Dijkstra

      1 Reply Last reply
      0
      • J John R Shaw

        I have taken to writing small papers and decided to share this excerpt, from “The Unforeseen Problem”, with the members of CP. Problem Two – The Unforeseen Problem The sponsor of the project created some files containing very large fonts and the degree symbol was not displaying, do to an obvious calculation error. But where was the error occurring, as there where several processes that the main program used when translating the data into visual information. At first it appeared to be in the drawing process, but that, along with every thing else, had been working perfectly for ten years and it had no knowledge of where the image data came from. This implied that the image data must be wrong and because the file contained the correct data, it was not a file format problem. So I examined the code for loading the individual characters from the file into the pattern page buffer and came upon the following line of code: offset = (*pszText++) * font_size; That code seems straight forward enough and to the untrained eye it appears to be correct. The problem with this code is that of conversion from one variable type to another; in the C language the result is calculated by up-converting the smallest variable type to the largest type in the equation and then storing the result using that type. The equation on the right-hand side consists of an unsigned character (8-bit integer) and an unsigned short (16-bit integer), which means that the result will be an unsigned short value. The left-hand side of the equation is an unsigned long (32-bit integer), which is just used to store the result and is not used, by the right-hand side, when determining the largest variable type required. Therefore the result can never be greater than 65536 and any attempt to calculate a number greater than that will result in wrapping, which basically mean the result will be the difference of the value expected and 65536, as in the following: 176 * 414 = 7328, which is incorrect and is equivalent to 72864 – 65536. The solution is to specify the type required to store the result on the right-hand side of the equation by manually up-converting one of the variables before the calculation occurs: offset = (unsigned long)(*pszText++) * font_size; The above solution is simple and could easily have been provided by the original creator of the program. I blame myself, in part, because I was the one who had to come in and fix the dozens of problems with the original program, back

        A Offline
        A Offline
        Antony M Kancidrowski
        wrote on last edited by
        #8

        Aw the joys of 16-bit programming on Windows 3.1 :)

        Ant. I'm hard, yet soft.
        I'm coloured, yet clear.
        I'm fruity and sweet.
        I'm jelly, what am I? Muse on it further, I shall return!
        - David Walliams (Little Britain)

        1 Reply Last reply
        0
        • W Warren Stevens

          John R. Shaw wrote:

          The equation on the right-hand side consists of an unsigned character (8-bit integer) and an unsigned short (16-bit integer), which means that the result will be an unsigned short value. The left-hand side of the equation is an unsigned long (32-bit integer)

          I know this is 1995 code, but I would hope that no one is using 8-bit or 16-bit integer types when writing any new code (in the age of $1/GB hard disks) :sigh: I'm also not a fan of unsigned types. With the conversion of -1 to a huge number (who thought allowing that conversion was a good idea ?!?) they're more trouble than they're worth. The moral of the story is: "use int for all integer data".


          www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

          N Offline
          N Offline
          NoCake
          wrote on last edited by
          #9

          Warren Stevens wrote:

          know this is 1995 code, but I would hope that no one is using 8-bit or 16-bit integer types when writing any new code (in the age of $1/GB hard disks)

          If you know you can get away with it, why not? There's a performance consideration. If I can define a colour as 4 bytes rather than 4 ints, then the colour fits nicely into a 32bit register, I can work on an large array of colours with x4 fewer cache hits, and it'll save bus bandwidth if I transfer that colour data to, say, a graphics card. In non-performance critical code, I would agree - use ints. Horses for courses, and all that.

          W R 2 Replies Last reply
          0
          • N NoCake

            Warren Stevens wrote:

            know this is 1995 code, but I would hope that no one is using 8-bit or 16-bit integer types when writing any new code (in the age of $1/GB hard disks)

            If you know you can get away with it, why not? There's a performance consideration. If I can define a colour as 4 bytes rather than 4 ints, then the colour fits nicely into a 32bit register, I can work on an large array of colours with x4 fewer cache hits, and it'll save bus bandwidth if I transfer that colour data to, say, a graphics card. In non-performance critical code, I would agree - use ints. Horses for courses, and all that.

            W Offline
            W Offline
            Warren Stevens
            wrote on last edited by
            #10

            NoCake wrote:

            If you know you can get away with it, why not? There's a performance consideration.

            Why not? Because there is always a trade-off. You're trading an increase in speed for an increase in complexity in your code, and more chance of overflow bugs. You can argue about how much complexity and overflow potential there is, but you have to agree that overflow bugs are very NASTY to track down. I'd rather minimize that chance altogether (and you cannot say "make sure the range of data always fits in the smaller type" because that's equivalent to "just write code without bugs"). Nowadays, if something is too slow at 2Ghz, I don't think it's a good idea to even bother trying to tweak code to get an extra 10 or 15% speed improvement. The better thing to do is to change "algorithms" (e.g. using a hash-table, or some other fast-lookup method) or change technologies (e.g. moving from GDI to DirectX) or make your algorithm multi-threaded, so multi-core chips will make it much faster. That's just my opinion (obviously there is no definitive right or wrong answer) :)


            www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

            N 1 Reply Last reply
            0
            • W Warren Stevens

              NoCake wrote:

              If you know you can get away with it, why not? There's a performance consideration.

              Why not? Because there is always a trade-off. You're trading an increase in speed for an increase in complexity in your code, and more chance of overflow bugs. You can argue about how much complexity and overflow potential there is, but you have to agree that overflow bugs are very NASTY to track down. I'd rather minimize that chance altogether (and you cannot say "make sure the range of data always fits in the smaller type" because that's equivalent to "just write code without bugs"). Nowadays, if something is too slow at 2Ghz, I don't think it's a good idea to even bother trying to tweak code to get an extra 10 or 15% speed improvement. The better thing to do is to change "algorithms" (e.g. using a hash-table, or some other fast-lookup method) or change technologies (e.g. moving from GDI to DirectX) or make your algorithm multi-threaded, so multi-core chips will make it much faster. That's just my opinion (obviously there is no definitive right or wrong answer) :)


              www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

              N Offline
              N Offline
              NoCake
              wrote on last edited by
              #11

              It's true, overflow bugs are awful. I totally agree that in non-performance -critical sections of code, give wide margins for error. In performance-critical stuff, especially library code, I'd shave off as many bits as I thought reasonable, and add appropriate asserts to ensure that any input into my data structures was in the correct range. You're right that the biggest optimisation win is to change your algorithms, but where that's not possible, second and third order effects like cache coherency, register usage, and so forth are very important. (i work in the games industry, where i get beaten if I write wasteful code :) ).

              W 1 Reply Last reply
              0
              • N NoCake

                It's true, overflow bugs are awful. I totally agree that in non-performance -critical sections of code, give wide margins for error. In performance-critical stuff, especially library code, I'd shave off as many bits as I thought reasonable, and add appropriate asserts to ensure that any input into my data structures was in the correct range. You're right that the biggest optimisation win is to change your algorithms, but where that's not possible, second and third order effects like cache coherency, register usage, and so forth are very important. (i work in the games industry, where i get beaten if I write wasteful code :) ).

                W Offline
                W Offline
                Warren Stevens
                wrote on last edited by
                #12

                NoCake wrote:

                i work in the games industry

                Games are a special case - hey do need that extra few percent of performance. But my comments stand for most everything else.

                NoCake wrote:

                i get beaten if I write wasteful code

                Sounds like EA ? ;P:-D


                www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

                D 1 Reply Last reply
                0
                • W Warren Stevens

                  NoCake wrote:

                  i work in the games industry

                  Games are a special case - hey do need that extra few percent of performance. But my comments stand for most everything else.

                  NoCake wrote:

                  i get beaten if I write wasteful code

                  Sounds like EA ? ;P:-D


                  www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

                  D Offline
                  D Offline
                  Dan Neely
                  wrote on last edited by
                  #13

                  Warren Stevens wrote:

                  Games are a special case - hey do need that extra few percent of performance. But my comments stand for most everything else.

                  Scientific computing is the other major exception, when you're running on a billion dollar supercomputer and are paying by the hour, or are using a DC system and can't directly increase the number of users running your app even small gains can pay large dividends in either runtime or iterative depth for algorithms that benefit from being run in increasingly long loops.

                  -- Rules of thumb should not be taken for the whole hand.

                  W 1 Reply Last reply
                  0
                  • D Dan Neely

                    Warren Stevens wrote:

                    Games are a special case - hey do need that extra few percent of performance. But my comments stand for most everything else.

                    Scientific computing is the other major exception, when you're running on a billion dollar supercomputer and are paying by the hour, or are using a DC system and can't directly increase the number of users running your app even small gains can pay large dividends in either runtime or iterative depth for algorithms that benefit from being run in increasingly long loops.

                    -- Rules of thumb should not be taken for the whole hand.

                    W Offline
                    W Offline
                    Warren Stevens
                    wrote on last edited by
                    #14

                    dan neely wrote:

                    Scientific computing is the other major exception, when you're running on a billion dollar supercomputer

                    Yes there are other niche markets besides games (how many people code for billion-dollar computers??? now that's a niche!) I've done scientific computing (not on the that large scale), and I always found it to be mostly ignored by the mainstream computing world (which is always talking about CRUD database apps). But... ...the main thrust of my argument was that in the "safer vs. faster" battle, safer has won. There will always be exceptions to this (games are the best example), but in general, people are willing to trade off a lot of speed for the prospect of less bugs. Witness the rise of protected memory, garbage collected languages, virtual machines, etc. :)Compared to the overhead of these systems, you're saving almost nothing by changing the size of your types (some odd cases excepted).


                    www.IconsReview.com[^] Huge list of stock icon collections (both free and commercial)

                    1 Reply Last reply
                    0
                    • N NoCake

                      Warren Stevens wrote:

                      know this is 1995 code, but I would hope that no one is using 8-bit or 16-bit integer types when writing any new code (in the age of $1/GB hard disks)

                      If you know you can get away with it, why not? There's a performance consideration. If I can define a colour as 4 bytes rather than 4 ints, then the colour fits nicely into a 32bit register, I can work on an large array of colours with x4 fewer cache hits, and it'll save bus bandwidth if I transfer that colour data to, say, a graphics card. In non-performance critical code, I would agree - use ints. Horses for courses, and all that.

                      R Offline
                      R Offline
                      ricecake
                      wrote on last edited by
                      #15

                      NoCake wrote:

                      If I can define a colour as 4 bytes rather than 4 ints, then the colour fits nicely into a 32bit register, I can work on an large array of colours with x4 fewer cache hits, and it'll save bus bandwidth if I transfer that colour data to, say, a graphics card.

                      However, depending on the system you are using, reads and writes might be slower depending on the system's alignment requirements. For example, you may be able to store four 8-bit bytes in one 32-bit word, but if the system can only read whole words at a time, then each access would need extra instructions to mask and shift the word, possibly slowing down the code. But as you said, the cache effects could outweigh these extra steps. So, it's very difficult to predict with a high degree of accuracy what will happen. The moral of the story is that you need to profile to make sure what you're doing has the effect that you want.

                      -- Marcus Kwok

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups