Floating point support not loaded

L

lolzy

Good day!


When I use this function, I get the following output:

runtime error R6002
- floating point support not loaded


Note:
- safeMalloc() is a safe function with error handling.
- sizeof(string) >= sizeof(buf) (so no overflows)



/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
int i = 0;
char *buf = safeMalloc(((strlen(string) * 3) + 1) * sizeof(char));
buf[0] = '\0';

while (string != '\0')
{
if (isalnum(string) || string == '-' || string == '_' ||
string == '.' || string == '~' || string == ' ')
{
if (string == ' ') string = '+';
sprintf(buf, "%s%c", buf, string);
}
else
{
sprintf(buf, "%s%%%.2X", buf, string);
}

++i;
}

strcpy(string, buf);
free(buf);
}


Yours Sincerely,
Jori.
 
M

Malcolm McLean

בת×ריך ×™×•× ×©×‘×ª,24 במרס 2012 10:04:44 UTC, מ×ת (e-mail address removed):
When I use this function, I get the following output:

runtime error R6002
- floating point support not loaded

[function, including]
sprintf(buf, "%s%%%.2X", buf, string);

Probably sprintf automatically drags in the code to covert the %f and %g specifiers. The compiler isn't smart enough to realise they aren't actually needed. Since you don't have floating point enabled, it complains.
 
E

Eric Sosman

Good day!


When I use this function, I get the following output:

runtime error R6002
- floating point support not loaded

This sounds very much like Question 14.13 on the comp.lang.c
Frequently Asked Questions (FAQ) page at <http://www.c-faq.com/>,
although it may be different in detail. That's a reasonable place
to start, anyhow.

Your code has other problems, though. I've spotted a few:
Note:
- safeMalloc() is a safe function with error handling.
- sizeof(string)>= sizeof(buf) (so no overflows)



/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
int i = 0;
char *buf = safeMalloc(((strlen(string) * 3) + 1) * sizeof(char));
buf[0] = '\0';

You probably won't need this (see below).
while (string != '\0')
{
if (isalnum(string) || string == '-' || string == '_' ||
string == '.' || string == '~' || string == ' ')


Use `isalnum( (unsigned char)string )' as the first part of
the test. Otherwise you're likely to get into trouble when dealing
with "exotic" characters on systems where `char' is signed.
{
if (string == ' ') string = '+';


It might have been smoother to treat the space character as a
case of its own. As things stand, you're making a special test to
include it in this case, and then making another test to give it
special treatment. (General principle: If you find yourself writing
two tests for the same condition, consider whether rearranging to
eliminate one test would lead to simpler code.)
sprintf(buf, "%s%c", buf, string);


Here's where the really serious trouble begins: "If copying
takes place between objects that overlap, the behavior is undefined"
(section 7.21.6.6 paragraph 2 of the C Standard). In this instance,
the code tries to copy from `buf' to `buf', and since `buf' clearly
overlaps itself there's no telling what might happen. One remedy
might be to append the new material without copying the old:

sprintf(buf + strlen(buf), "%c", string);

To my taste, though, that's a lot of machinery just to copy a single
character from one place to another! If I were writing the code, I
think I'd maintain a second pointer like `char *end;' whose job is
to point just after the last character deposited in `buf'. It would
start out equal to `buf' and would advance as characters were
appended. Using such a pointer, you could replace this line with

*end++ = string;

.... which I think you'll agree is a much "lighter-weight" solution.
Note that this copies only one character, meaning that `buf' will
not have a '\0' at the end -- but that's all right, because you
don't need `buf' to hold a well-formed string until you've finished
converting all of `string'.
}
else
{
sprintf(buf, "%s%%%.2X", buf, string);


Same problem with overlap, with similar solutions. In this
case it's probably easier to let sprintf() take care of the hex
conversion, so you'd have

end += sprintf(end, "%%%.2X", string);

If you're using the `end' pointer as I suggest, at this point
you need to supply a '\0' to ensure a well-formed string before
calling strcpy() on it:

*end = '\0';
 
L

lolzy

Good day!
When I use this function, I get the following output:
runtime error R6002
- floating point support not loaded

     This sounds very much like Question 14.13 on the comp.lang.c
Frequently Asked Questions (FAQ) page at <http://www.c-faq.com/>,
although it may be different in detail.  That's a reasonable place
to start, anyhow.

     Your code has other problems, though.  I've spotted a few:


Note:
- safeMalloc() is a safe function with error handling.
- sizeof(string)>= sizeof(buf) (so no overflows)
/*
  * Encode a string according tohttp://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
   int i = 0;
   char *buf = safeMalloc(((strlen(string) * 3) + 1) * sizeof(char));
buf[0] = '\0';

     You probably won't need this (see below).
   while (string != '\0')
   {
           if (isalnum(string) || string == '-' || string == '_' ||
string == '.' || string == '~' || string == ' ')


     Use `isalnum( (unsigned char)string )' as the first part of
the test.  Otherwise you're likely to get into trouble when dealing
with "exotic" characters on systems where `char' is signed.
           {
                   if (string == ' ') string = '+';


     It might have been smoother to treat the space character as a
case of its own.  As things stand, you're making a special test to
include it in this case, and then making another test to give it
special treatment.  (General principle: If you find yourself writing
two tests for the same condition, consider whether rearranging to
eliminate one test would lead to simpler code.)
                   sprintf(buf, "%s%c", buf, string);


     Here's where the really serious trouble begins: "If copying
takes place between objects that overlap, the behavior is undefined"
(section 7.21.6.6 paragraph 2 of the C Standard).  In this instance,
the code tries to copy from `buf' to `buf', and since `buf' clearly
overlaps itself there's no telling what might happen.  One remedy
might be to append the new material without copying the old:

        sprintf(buf + strlen(buf), "%c", string);

To my taste, though, that's a lot of machinery just to copy a single
character from one place to another!  If I were writing the code, I
think I'd maintain a second pointer like `char *end;' whose job is
to point just after the last character deposited in `buf'.  It would
start out equal to `buf' and would advance as characters were
appended.  Using such a pointer, you could replace this line with

        *end++ = string;

... which I think you'll agree is a much "lighter-weight" solution.
Note that this copies only one character, meaning that `buf' will
not have a '\0' at the end -- but that's all right, because you
don't need `buf' to hold a well-formed string until you've finished
converting all of `string'.
           }
           else
           {
                   sprintf(buf, "%s%%%.2X", buf, string);


     Same problem with overlap, with similar solutions.  In this
case it's probably easier to let sprintf() take care of the hex
conversion, so you'd have

        end += sprintf(end, "%%%.2X", string);
           }
           ++i;
   }

     If you're using the `end' pointer as I suggest, at this point
you need to supply a '\0' to ensure a well-formed string before
calling strcpy() on it:

        *end = '\0';
   strcpy(string, buf);
   free(buf);
}


I totally agree with you. I wasn't finished optimizing the code
yet :). But I didn't knew of the 7.21.6.6.

Thanks a lot.
 
L

lolzy

/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
float test = sqrt(9);
int i = 0;
char *buf = KhSafeMalloc(((strlen(string) * 3) + 1) * sizeof(char)),
*end = buf;

while (string != '\0')
{
if ((unsigned char) isalnum(string) || string == '-' ||
string == '_' || string == '.' || string == '~')
*end++ = string;
else if (string == ' ')
*end++ = '+';
else
end += sprintf(end, "%%%.2X", string);

++i;
}

*end = '\0';
strcpy(string, buf);
free(buf);
}


'float test = sqrt(9)' did the trick :)
 
E

Eric Sosman

/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
float test = sqrt(9);

I guess this ensures the presence of floating-point support.
Seems like there ought to be a more direct way, though: possibly
a compiler or linker command-line option or something of that kind.
int i = 0;
char *buf = KhSafeMalloc(((strlen(string) * 3) + 1) * sizeof(char)),
*end = buf;

while (string != '\0')
{
if ((unsigned char) isalnum(string) || string == '-' ||


Not quite: `isalnum((unsigned char)string)' is what you want.

Here's the deal: In the dim mists of prehistory, the people who
invented what has become <ctype.h> thought it would be a good idea if
the functions could be applied not only to `char' values, but to any
value one might read from an input stream. A `char' value read by
the getc() function or any of its relatives is always non-negative,
making it easy to distinguish actual input from the special, negative
EOF value that means "no input: finished or failed." So that's what
the isxxx() functions require for their arguments: Either the negative
EOF value or a non-negative `char' value.

There are several problems with this scheme. The one that's of
concern here is that `char' itself is unsigned on some systems, but
signed on others. The "basic execution character set" values are
all non-negative (6.2.5p3), but additional characters may be positive
or negative: Try a few like âĕïòú and you might see negative values.
To avoid this issue, getc() and friends return actual characters as
the values they would have if converted to `unsigned char' and then
stored in an `int'.

But if you pluck a `char' value from a string, you might wind
up with a negative value (for some characters on some systems).
If you feed this value to isxxx() or toxxx() you are asking for
trouble: The *only* valid negative argument value for these functions
is EOF, and the behavior is undefined if you pass some other negative
value (7.4p1). On many systems these "functions" are implemented as
macros that use the argument as an array index, and you'll wind up
indexing into the never-never-land that lies before the array, with
unpredictable consequences. It's unfortunate, but in the name of
"backward compatibility" it's too late to change.
string == '_' || string == '.' || string == '~')
*end++ = string;
else if (string == ' ')
*end++ = '+';
else
end += sprintf(end, "%%%.2X", string);

++i;
}

*end = '\0';
strcpy(string, buf);
free(buf);
}


'float test = sqrt(9)' did the trick :)
 
K

Keith Thompson

/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
float test = sqrt(9);
int i = 0;
char *buf = KhSafeMalloc(((strlen(string) * 3) + 1) * sizeof(char)),
*end = buf;

while (string != '\0')
{
if ((unsigned char) isalnum(string) || string == '-' ||
string == '_' || string == '.' || string == '~')
*end++ = string;
else if (string == ' ')
*end++ = '+';
else
end += sprintf(end, "%%%.2X", string);

++i;
}

*end = '\0';
strcpy(string, buf);
free(buf);
}


'float test = sqrt(9)' did the trick :)


It's likely that you don't actually have to *execute* the call to the
sqrt() function to cause floating point support to be loaded. Try
something like:

float test = 0 ? sqrt(9) : 0;

or perhaps even:

sqrt;

The latter is not a call to sqrt; it's an expression that evaluates to
the address of the sqrt function. Since the result is discarded, it
shouldn't generate any actual code, but it might force the compiler to
load the floating-point code anyway.

In both cases, a sufficiently clever compiler can recognize that the
code has no effect and eliminate it -- but your compiler is
insufficiently clever either to load the floating-point code or to
recognize that it doesn't need it.

Of course you should have "#include <math.h>" if you refer to the sqrt
function.
 
M

Markus Wichmann

/*
* Encode a string according to http://tools.ietf.org/html/rfc3986#section-2.1.
*/
void urlEncode(char *string)
{
float test = sqrt(9);
int i = 0;
char *buf = KhSafeMalloc(((strlen(string) * 3) + 1) * sizeof(char)),
*end = buf;

while (string != '\0')
{
if ((unsigned char) isalnum(string) || string == '-' ||
string == '_' || string == '.' || string == '~')
*end++ = string;
else if (string == ' ')
*end++ = '+';
else
end += sprintf(end, "%%%.2X", string);

++i;
}

*end = '\0';
strcpy(string, buf);
free(buf);
}


'float test = sqrt(9)' did the trick :)


It's likely that you don't actually have to *execute* the call to the
sqrt() function to cause floating point support to be loaded. Try
something like:

float test = 0 ? sqrt(9) : 0;

or perhaps even:

sqrt;

The latter is not a call to sqrt; it's an expression that evaluates to
the address of the sqrt function. Since the result is discarded, it
shouldn't generate any actual code, but it might force the compiler to
load the floating-point code anyway.


Ever heard of dead code elimination? It's a very basic optimization that
would remove the reference to sqrt() and therefore the need to link
against libm (or whatever that system's equal of it is).
In both cases, a sufficiently clever compiler can recognize that the
code has no effect and eliminate it -- but your compiler is
insufficiently clever either to load the floating-point code or to
recognize that it doesn't need it.

That's another can of worms. The way I see it, the designers of that
system's *scanf() did a bad job, because they depend on floating-point
support at runtime, but don't tell anyone during link time. My take on
it is that the compiler tries linking without libm and if that doesn't
work, tries it with libm. Maybe even something bigger, like linking
against nothing but libc, writing down all the "undefined reference"
errors and looking up the symbols in the libraries directory, then
linking in all the necessary libraries. Basically what you would get
with GNU ld and zsh and

ld -I/lib/ld-linux.so.2 -o output *.o --as-needed {/usr,}/lib/**/*.so

But somehow those guys wrote scanf() to not directly reference libm, so
this code doesn't see that it should include libm.

See the problem? The compiler can have all optimizations in the world,
here the linker and library conspire together to not make it work. If
you ask me, switch compilers!
Of course you should have "#include <math.h>" if you refer to the sqrt
function.

That's true, too.

Ciao,
Markus
 
J

James Kuyper

On 24.03.2012 22:34, Keith Thompson wrote: ....

Ever heard of dead code elimination? It's a very basic optimization that
would remove the reference to sqrt() and therefore the need to link
against libm (or whatever that system's equal of it is).

I'm sure he has, since he mentions it in the very next line of his that
you quoted. The use of sqrt is just a trick that shouldn't be necessary
when using a fully conforming implementation of C. If this
implementation requires special command line options to load the
floating point math support needed by printf(), then it isn't fully
conforming without those options selected.
That's another can of worms. The way I see it, the designers of that
system's *scanf() did a bad job, because they depend on floating-point
support at runtime, but don't tell anyone during link time. My take on
it is that the compiler tries linking without libm and if that doesn't
work, tries it with libm. ...

I presume that one of those two "libm"s was supposed to be something else?
 
M

Markus Wichmann

I presume that one of those two "libm"s was supposed to be something else?

No. Perhaps I should add some emphasis: The linker first tries to link
_without_ libm. Then, if that doesn't work, the link is tried again,
this time _with_ libm.

Note that that is one possible explanation for the weird behaviour the
OP is experiencing. The real reason may be something entirely different.
Still, what I meant by the above is that the compiler can't be faulted
for mistakes of linker and library.

Ciao,
Markus
 
J

James Kuyper

No. Perhaps I should add some emphasis: The linker first tries to link
_without_ libm. Then, if that doesn't work, the link is tried again,
this time _with_ libm.

Sorry - I somehow managed to misread "without" as "with".
Note that that is one possible explanation for the weird behaviour the
OP is experiencing. ...

It's a possible linkage strategy, but if it is followed, then a failure
to find needed symbols during the first (without libm) pass shouldn't
cause a warning message, much less an error message accompanied by a
linkage failure. That should only occur if the symbols are not found on
the second (with libm) pass.
... The real reason may be something entirely different.
Still, what I meant by the above is that the compiler can't be faulted
for mistakes of linker and library.

Producing a fatal linkage error before having attempted to link to all
of the libraries it's supposed to be searching is a pretty severe
mistake for the linker to make. In my experience (which is, admittedly,
based on a relatively small number of different implementations of C),
the compiler normally tells the linker what libraries to search for; the
linker just followings those instructions - in which case it is indeed
the compiler's fault for issuing bad instructions.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top