首页
社区
课程
招聘
[原创]第一阶段第三题提交
发表于: 2008-10-8 16:50 3258

[原创]第一阶段第三题提交

2008-10-8 16:50
3258
这个程序用VC8所编写。
VC8的c++支持多种CPU,其中包括一些不能做浮点数运算的CPU。
于是语言设计的时候把浮点运算模块独立出来,
这意味着:

output部分和浮点运算部分可以在不同模块实现

事实上, vc也是这么做的, 这样如果对不同CPU移植的话
只需要改写fpu模块, 而不需要改写output io模块
而为了除错, 当浮点模块没有实现的时候,crt0fp.c有一个默认的实现
即void _fptrap(), 简单的就是说给你一个msg说找不到浮点处理例程,
然后程序退出,而作为遵守约定, 有实现模块实现了的话,
当处理浮点运算时,则能够顺利进行。
有些人说, 为什么不直接让output io去找连接导出函数,
而要做一个中转功能呢。
这是出于通用考虑, 可能某些CPU下没有浮点数对应的机器码,
而且程序也不需要进行浮点数运算, 这种情况下则可以不模拟实现
浮点指令, crt0fp.c已经实现了一套,
然而如果是直接找导出函数, 则必须默认实现一个,

于是:
在C++的runtime库初始化的时候, 根据处理器不同(编译选项不同
链接不同库)来初始化浮点运算器

// 参考下面这段代码

#ifdef CRTDLL
        _fpmath(initFloatingPrecision);
#else  /* CRTDLL */
        if (_FPinit != NULL &&
            _IsNonwritableInCurrentImage((PBYTE)&_FPinit))
        {
            (*_FPinit)(initFloatingPrecision);
        }

显然, 如果是动态连接的情况下, 则功能提交给dll执行(dll去做自己的pe检查等)
否则, 则自己PE合法性检查, 如果没问题在初始化。
_FPinit这个函数指针正常情况下是在.rdata中的, 他所在的节属性一定是只读的,
否则自检失败, 结果是浮点数没有初始化, 浮点函数都是那套默认实现。

这个mfc程序恰巧碰到这一点, 不知人为原因还是故意指定属性,导致节属性改变,
于是弹快退出了。

出错的函数在

                    _cfltcvt_l(&tmp.x, text.sz, buffersize, (char)ch, precision, capexp, _loc_update.GetLocaleT());

/*
* floating point helper routines
*
* In the non-CRTDLL builds, these prototypes are immediately replaced by
* macros which replace them with calls through elements of the _cfltcvt_tab
* array, so we only pull them into a static-link build if floating point
* code is needed.
*/

这里是个宏
(*((PF6)_CFLTCVT_TAB(6)))(a,b,c,d,e,f,g)

修改方式即把.rdata的节的writeable给删除。 参考修改过的exe.

===========================

另外vs2008, 编译有些BUG可能会导致编译器错误的认为你不需要fpu,如

int main()
{
   printf("%f", 3);   // error , no reference
}

int main()
{
   printf("%f", 3.0); // ok
}

//////////////////////
最后, 关于这个问题MSDN的解释
Error Message
floating-point support not loaded

The necessary floating-point library was not linked.

To fix by checking the following possible causes
The program was compiled or linked with an option, such as /FPi87, that requires a coprocessor, but the program was run on

a machine that did not have a coprocessor installed.

A format string for a printf_s or scanf_s function contained a floating-point format specification and the program did not

contain any floating-point values or variables.

The compiler minimizes a program's size by loading floating-point support only when necessary. The compiler cannot detect

floating-point format specifications in format strings, so it does not load the necessary floating-point routines.

Use a floating-point argument to correspond to the floating-point format specification, or perform a floating-point

assignment elsewhere in the program. This causes floating-point support to be loaded.

In a mixed-language program, a C library was specified before a FORTRAN library when the program was linked. Relink and

specify the C library last.

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 264
活跃值: (30)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
2
结果提交时间 4 小时 50 分钟
结果提交时间长度 = 290 分钟
结果提交次数 = 1
结果提交为根本原因
得分 = [(2880 - 290)/2880]^1/5 x 1.0 x 100 - (1 -1 ) x 5 = 97.90
2008-10-14 15:58
0
游客
登录 | 注册 方可回帖
返回
//