Is My Program OK?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Andy G.

    Is My Program OK?

    Greetings!

    I am learning C and I came up with this program to test my knowledge.

    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
    char s[128];
    void *p;
    sprintf(s, "%p", malloc(0x10));
    puts(s);
    sscanf(s, "%p", &p);
    printf("%p\n", p);
    free(p);
    return 0;
    }

    Is it OK? Even if malloc returns NULL?

    One thing I am not sure of is what the size of s should be. Is 128
    enough? Or too much? How should I know how big to make it?

    Thanks in advance -- Andy!
  • vippstar@gmail.com

    #2
    Re: Is My Program OK?

    On Feb 23, 10:26 am, "Andy G." <andyg...@spamc op.netwrote:
    Greetings!
    >
    I am learning C and I came up with this program to test my knowledge.
    >
    #include <stdio.h>
    #include <stdlib.h>
    int main(void)
    {
    char s[128];
    void *p;
    sprintf(s, "%p", malloc(0x10));
    puts(s);
    sscanf(s, "%p", &p);
    printf("%p\n", p);
    free(p);
    return 0;
    >
    }
    >
    Is it OK? Even if malloc returns NULL?
    Yes, except the sprintf() part.
    One thing I am not sure of is what the size of s should be. Is 128
    enough? Or too much? How should I know how big to make it?
    You cannot know whether it will fit or not.
    You should instead use snprintf() and check the return value.
    Also, save the pointer somewhere, in case it does not fit in the
    buffer so you can free it.

    Comment

    • Vitillo Roberto

      #3
      Re: Is My Program OK?

      You cannot know whether it will fit or not.
      Are you sure? This should do the trick:

      int mod = -1;
      int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
      sizeof(char) : sizeof(void*)/sizeof(char)+1;
      char s[len];

      Comment

      • Bartc

        #4
        Re: Is My Program OK?


        "Vitillo Roberto" <r.vitillo@gmai l.comwrote in message
        news:1ad52cfa-4dac-4723-abaf-78920267f1f4@p7 3g2000hsd.googl egroups.com...
        >You cannot know whether it will fit or not.
        Are you sure? This should do the trick:
        >
        int mod = -1;
        int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
        sizeof(char) : sizeof(void*)/sizeof(char)+1;
        char s[len];
        I think if my life depended on getting len absolutely right, I would rather
        take my chances with len=128.

        Especially as your code seems to give len=4 :-)

        --
        Bart


        Comment

        • Roberto V.

          #5
          Re: Is My Program OK?

          Ups...
          int mod = -1;
          int len = ((mod = sizeof(void*)*2 % sizeof(char)) == 0) ?
          sizeof(void*)*2/sizeof(char) : sizeof(void*)*2/sizeof(char)+1;
          char s[len+1];

          Better now? ;)

          Comment

          • santosh

            #6
            Re: Is My Program OK?

            vippstar@gmail. com wrote:
            On Feb 23, 10:26 am, "Andy G." <andyg...@spamc op.netwrote:
            >Greetings!
            >>
            >I am learning C and I came up with this program to test my knowledge.
            >>
            >#include <stdio.h>
            >#include <stdlib.h>
            >int main(void)
            >{
            > char s[128];
            > void *p;
            > sprintf(s, "%p", malloc(0x10));
            > puts(s);
            > sscanf(s, "%p", &p);
            > printf("%p\n", p);
            > free(p);
            > return 0;
            >>
            >}
            >>
            >Is it OK? Even if malloc returns NULL?
            Yes, except the sprintf() part.
            >One thing I am not sure of is what the size of s should be. Is 128
            >enough? Or too much? How should I know how big to make it?
            You cannot know whether it will fit or not.
            You should instead use snprintf() and check the return value.
            Also, save the pointer somewhere, in case it does not fit in the
            buffer so you can free it.
            One more minor point is to cast the argument to printf to a void *,
            since the %p specifier is defined as accepting a void pointer value
            only.

            Maybe also change 's' to unsigned char[].

            Comment

            • vippstar@gmail.com

              #7
              Re: Is My Program OK?

              On Feb 23, 2:33 pm, santosh <santosh....@gm ail.comwrote:
              vipps...@gmail. com wrote:
              On Feb 23, 10:26 am, "Andy G." <andyg...@spamc op.netwrote:
              Greetings!
              >
              I am learning C and I came up with this program to test my knowledge.
              >
              #include <stdio.h>
              #include <stdlib.h>
              int main(void)
              {
              char s[128];
              void *p;
              sprintf(s, "%p", malloc(0x10));
              puts(s);
              sscanf(s, "%p", &p);
              printf("%p\n", p);
              free(p);
              return 0;
              >
              }
              >
              Is it OK? Even if malloc returns NULL?
              Yes, except the sprintf() part.
              One thing I am not sure of is what the size of s should be. Is 128
              enough? Or too much? How should I know how big to make it?
              You cannot know whether it will fit or not.
              You should instead use snprintf() and check the return value.
              Also, save the pointer somewhere, in case it does not fit in the
              buffer so you can free it.
              >
              One more minor point is to cast the argument to printf to a void *,
              since the %p specifier is defined as accepting a void pointer value
              only.
              That is not needed in the source mr Andy G. posted.

              Comment

              • Ben Bacarisse

                #8
                Re: Is My Program OK?

                Vitillo Roberto <r.vitillo@gmai l.comwrites:
                >You cannot know whether it will fit or not.
                Are you sure? This should do the trick:
                >
                int mod = -1;
                int len = ((mod = sizeof(void*) % sizeof(char)) == 0) ? sizeof(void*)/
                sizeof(char) : sizeof(void*)/sizeof(char)+1;
                char s[len];
                Nothing about sizeof(void *) can tell you the required output size.
                It could tell you something about the possible number of different
                pointer values, but that is not the same thing. %p might produce:

                <segment: 0x2345 offset: 2998788765 in cluster main:24>

                who knows?

                --
                Ben.

                Comment

                • santosh

                  #9
                  Re: Is My Program OK?

                  vippstar@gmail. com wrote:
                  On Feb 23, 2:33 pm, santosh <santosh....@gm ail.comwrote:
                  >vipps...@gmail .com wrote:
                  On Feb 23, 10:26 am, "Andy G." <andyg...@spamc op.netwrote:
                  >Greetings!
                  >>
                  >I am learning C and I came up with this program to test my
                  >knowledge.
                  >>
                  >#include <stdio.h>
                  >#include <stdlib.h>
                  >int main(void)
                  >{
                  > char s[128];
                  > void *p;
                  > sprintf(s, "%p", malloc(0x10));
                  > puts(s);
                  > sscanf(s, "%p", &p);
                  > printf("%p\n", p);
                  > free(p);
                  > return 0;
                  >>
                  >}
                  >>
                  >Is it OK? Even if malloc returns NULL?
                  Yes, except the sprintf() part.
                  >One thing I am not sure of is what the size of s should be. Is 128
                  >enough? Or too much? How should I know how big to make it?
                  You cannot know whether it will fit or not.
                  You should instead use snprintf() and check the return value.
                  Also, save the pointer somewhere, in case it does not fit in the
                  buffer so you can free it.
                  >>
                  >One more minor point is to cast the argument to printf to a void *,
                  >since the %p specifier is defined as accepting a void pointer value
                  >only.
                  That is not needed in the source mr Andy G. posted.
                  Ah yes. My bad.

                  Comment

                  • Peter Nilsson

                    #10
                    Re: Is My Program OK?

                    "Andy G." <andyg...@spamc op.netwrote:
                    #include <stdio.h>
                    #include <stdlib.h>
                    int main(void)
                    {
                      char s[128];
                      void *p;
                      sprintf(s, "%p", malloc(0x10));
                      puts(s);
                      sscanf(s, "%p", &p);
                      printf("%p\n", p);
                      free(p);
                      return 0;
                    >
                    }
                    >
                    Is it OK? Even if malloc returns NULL?
                    >
                    One thing I am not sure of is what the size of s should
                    be. Is 128 enough? Or too much? How should I know how
                    big to make it?
                    No, yes and this big respectively. :-)

                    Other advice notwithstanding , if you actually want to
                    print a pointer, even with the possibility of scanning
                    it back later, then you should print and scan the
                    representation as an array of unsigned char. The size
                    (of hex output say) can be computed at compile time.

                    --
                    Peter

                    Comment

                    • Kenneth Brody

                      #11
                      Re: Is My Program OK?

                      CBFalconer wrote:
                      >
                      Kenneth Brody wrote:
                      [... size needed for "%p" output ...]
                      You *cannot* know the size.
                      <pedant>
                      Well, you can "know" it at runtime, with snprintf():

                      7.19.6.5p3

                      The snprintf function returns the number of characters that
                      would have been written had n been sufficiently large, not
                      counting the terminating null character, or a negative value
                      if an encoding error occurred.
                      </pedant>
                      >
                      The C standard for fprintf says:
                      [... returns length or negative for error ...]
                      and for printf says:
                      [... returns length or negative for error ...]
                      which seem to provide an adequate means of determining the size
                      written. Similarly for sprintf. Amazingly enough, these also
                      allow detecting i/o errors in the output stream.
                      But, how big should you make the buffer for sprintf(), as the OP
                      was using?

                      --
                      +-------------------------+--------------------+-----------------------+
                      | Kenneth J. Brody | www.hvcomputer.com | #include |
                      | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer .h|
                      +-------------------------+--------------------+-----------------------+
                      Don't e-mail me at: <mailto:ThisIsA SpamTrap@gmail. com>

                      Comment

                      • Willem

                        #12
                        Re: Is My Program OK?

                        CBFalconer wrote:
                        ) The C standard for fprintf says:
                        <snip(returns the number printed, or negative)
                        ) and for printf says:
                        <snip>
                        ) which seem to provide an adequate means of determining the size
                        ) written. Similarly for sprintf.

                        Indeed, you can check that sprintf has gone beyond the bounds of your
                        buffer. _After_ it has clobbered whatever happened to be located behind
                        it (or invoked some other form of UB). Oopsie.


                        SaSW, Willem
                        --
                        Disclaimer: I am in no way responsible for any of the statements
                        made in the above text. For all I know I might be
                        drugged or something..
                        No I'm not paranoid. You all think I'm paranoid, don't you !
                        #EOT

                        Comment

                        • Antoninus Twink

                          #13
                          Re: Is My Program OK?

                          On 26 Feb 2008 at 20:19, Kenneth Brody wrote:
                          CBFalconer wrote:
                          >>
                          >Kenneth Brody wrote:
                          [... size needed for "%p" output ...]
                          >You *cannot* know the size.
                          >
                          <pedant>
                          Well, you can "know" it at runtime, with snprintf():
                          >
                          7.19.6.5p3
                          >
                          The snprintf function returns the number of characters that
                          would have been written had n been sufficiently large, not
                          counting the terminating null character, or a negative value
                          if an encoding error occurred.
                          </pedant>
                          >>
                          >The C standard for fprintf says:
                          [... returns length or negative for error ...]
                          >and for printf says:
                          [... returns length or negative for error ...]
                          >which seem to provide an adequate means of determining the size
                          >written. Similarly for sprintf. Amazingly enough, these also
                          >allow detecting i/o errors in the output stream.
                          >
                          But, how big should you make the buffer for sprintf(), as the OP
                          was using?
                          You can fprintf it to /dev/null (or NUL), collect the return value, and
                          then make the buffer that big for sprinf() with the same format string
                          and arguments.

                          Of course, that can't be what CBF had in mind as it's off-topic, not
                          portable, not C, can't discuss it, blah blah.

                          Comment

                          • jaysome

                            #14
                            Re: Is My Program OK?

                            On Tue, 26 Feb 2008 15:19:33 -0500, Kenneth Brody
                            <kenbrody@spamc op.netwrote:
                            >CBFalconer wrote:
                            >>
                            >Kenneth Brody wrote:
                            >[... size needed for "%p" output ...]
                            >You *cannot* know the size.
                            >
                            <pedant>
                            Well, you can "know" it at runtime, with snprintf():
                            >
                            7.19.6.5p3
                            >
                            The snprintf function returns the number of characters that
                            would have been written had n been sufficiently large, not
                            counting the terminating null character, or a negative value
                            if an encoding error occurred.
                            </pedant>
                            >>
                            >The C standard for fprintf says:
                            >[... returns length or negative for error ...]
                            >and for printf says:
                            >[... returns length or negative for error ...]
                            >which seem to provide an adequate means of determining the size
                            >written. Similarly for sprintf. Amazingly enough, these also
                            >allow detecting i/o errors in the output stream.
                            >
                            >But, how big should you make the buffer for sprintf(), as the OP
                            >was using?
                            The C Standard says this about the "%p" conversion specification:

                            "The argument shall be a pointer to void. The value of the pointer is
                            converted to a sequence of printing characters, in an
                            implementation-defined manner."

                            This means that this program:

                            #include <stdio.h>
                            int main(void)
                            {
                            printf("%p\n", (void*)0);
                            return 0;
                            }

                            can produce the following output in a strictly conforming
                            implementation:

                            The quick brown fox jumps over the lazy dog.

                            It could also output the text of The Declaration of Independence or of
                            the book War and Peace. In other words, strictly speaking, the answer
                            to the OP's question is: we don't know and we can't say.

                            Practically speaking, though, a buffer size that is a generous power
                            of 2 will work. I'd be comfortable with s[16], but personally I'd use
                            a very cheap s[32] just for good measure.

                            In my experience, sprintf'ing a pointer value to a string (in, for
                            example, a debug log message), requires that you use a size for the
                            string that is sufficient in size by eyeballing it. For example:

                            char s[128];
                            sprintf("p is %p\n", (void*)p);

                            Although the size 128 is, strictly speaking, not guaranteed to be
                            sufficient in size to accomodate the "%p" conversion specification
                            along with the accompanying text, it is sufficient for practical
                            purposes, all things considered.

                            --
                            jay

                            Comment

                            • santosh

                              #15
                              Re: Is My Program OK?

                              jaysome wrote:
                              On Tue, 26 Feb 2008 15:19:33 -0500, Kenneth Brody
                              <kenbrody@spamc op.netwrote:
                              >
                              >>CBFalconer wrote:
                              >>>
                              >>Kenneth Brody wrote:
                              >vippstar@gmail. com wrote:
                              >>[... size needed for "%p" output ...]
                              >>You *cannot* know the size.
                              >>
                              ><pedant>
                              >Well, you can "know" it at runtime, with snprintf():
                              >>
                              > 7.19.6.5p3
                              >>
                              > The snprintf function returns the number of characters that
                              > would have been written had n been sufficiently large, not
                              > counting the terminating null character, or a negative value
                              > if an encoding error occurred.
                              ></pedant>
                              >>>
                              >>The C standard for fprintf says:
                              >>[... returns length or negative for error ...]
                              >>and for printf says:
                              >>[... returns length or negative for error ...]
                              >>which seem to provide an adequate means of determining the size
                              >>written. Similarly for sprintf. Amazingly enough, these also
                              >>allow detecting i/o errors in the output stream.
                              >>
                              >>But, how big should you make the buffer for sprintf(), as the OP
                              >>was using?
                              >
                              The C Standard says this about the "%p" conversion specification:
                              >
                              "The argument shall be a pointer to void. The value of the pointer is
                              converted to a sequence of printing characters, in an
                              implementation-defined manner."
                              >
                              This means that this program:
                              >
                              #include <stdio.h>
                              int main(void)
                              {
                              printf("%p\n", (void*)0);
                              return 0;
                              }
                              >
                              can produce the following output in a strictly conforming
                              implementation:
                              >
                              The quick brown fox jumps over the lazy dog.
                              >
                              It could also output the text of The Declaration of Independence or of
                              the book War and Peace. In other words, strictly speaking, the answer
                              to the OP's question is: we don't know and we can't say.
                              >
                              Practically speaking, though, a buffer size that is a generous power
                              of 2 will work. I'd be comfortable with s[16], but personally I'd use
                              a very cheap s[32] just for good measure.
                              >
                              In my experience, sprintf'ing a pointer value to a string (in, for
                              example, a debug log message), requires that you use a size for the
                              string that is sufficient in size by eyeballing it. For example:
                              >
                              char s[128];
                              sprintf("p is %p\n", (void*)p);
                              >
                              Although the size 128 is, strictly speaking, not guaranteed to be
                              sufficient in size to accomodate the "%p" conversion specification
                              along with the accompanying text, it is sufficient for practical
                              purposes, all things considered.
                              I suppose the proper way to do this is:

                              char *ptr = "hello";
                              char *a;
                              int n = snprintf(NULL, 0, "%p", ptr);
                              if (n 0) {
                              a = malloc(n + 1);
                              if (!a) exit(EXIT_FAILU RE);
                              else {
                              int m;
                              m = snprintf(a, n + 1, "%p", ptr);
                              if (m < 0 || m < n) {
                              /* error */
                              }
                              }
                              }
                              else /* error */

                              Comment

                              Working...