LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1018|回复: 10

奇怪的优化结果

[复制链接]
发表于 2007-7-11 21:31:10 | 显示全部楼层 |阅读模式
最近在学习线程
下面是一段代码,故意没有将thread初始化:
thread_error.cpp
--------------------------------------------------------
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    pthread_t thread;
    int status;

    status = pthread_join(thread, NULL);
    if (status != 0)
        fprintf (stderr, "error %d: %s\n", status, strerror (status));
    return status;
}
--------------------------------------------------------
奇怪的是,
如果用g++ -O2 -D_REENTRANT -lpthread thread_error.cpp 编译运行的结果是:
error 3: No such process

如果用g++ -O0 -D_REENTRANT -lpthread thread_error.cpp 编译运行的结果是:
段错误

为何启用优化选项-O2得到的结果比不优化得到的结果还优雅?
不优化,运行是被粗暴的意外终止
优化,能正常结束程序。

哪位能指点一下?多谢~~
发表于 2007-7-12 09:20:44 | 显示全部楼层
这能说明什么呢?thread放在栈中。
两次运行,thread的值都是随机的不同的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-12 09:35:05 | 显示全部楼层
thread在使用前未初始化,当然每次运行都是随机值。
这个我明白。

重点是,使用-O0和-O2得到的运行结果不一样。
-O2能够正确运行status = pthread_join(thread, NULL);并返回
-O0则程序异常终止

我搞不明白的是这点。
前面已经说明,是故意将thread在使用前未初始化。

我以前的想法是,优化编译后的程序可能比不优化编译所得的程序行为上有些异常
而现在的现象却是,优化编译后的程序能正常结束,而不优化编译所得的程序却会异常终止。

还望版主继续指点,多谢~~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-12 09:39:43 | 显示全部楼层
另外说明一下,该代码片断的目的是用来了解Pthread接口函数对错误的处理方式。

传统函数是在调用失败时返回-1,然后用全局变量errno来表明具体的错误信息。
而Pthread接口函数则在成功时返回0,失败时返回错误代码。
回复 支持 反对

使用道具 举报

发表于 2007-7-12 11:35:58 | 显示全部楼层
一个可能是pthread_t内部的实现是一个指针,因为是随机的,所以第一个例子中,thread指针正好在进程的有效虚拟地址区间内,所以正确得到了结果。
而在第二个例子中,thread指针指向了进程的无效线虚拟地址区间内,所以段错。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-12 12:33:01 | 显示全部楼层
从现象上看,异常终止的情况确实象是非法访问内存之类的错误

但令人诧异的是,-O0编译的结果每次都会异常终止,-O2编译的结果每次都能正常结束。

这样,就无法用随机性来解释这两种编译结果的差别了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-12 13:02:03 | 显示全部楼层
man了一下pthread_create
只能说,实现上和要求有一些偏差。
回复 支持 反对

使用道具 举报

发表于 2007-7-12 13:35:46 | 显示全部楼层
这种问题是无法重现的。也许一段时间以后你再运行 -O0 的那个程序就不会段错误了。比如我这里:
error 22: Invalid argument

从编译器的角度来看,这被称为 undefined behaviour 。其运行结果是随机的,无法保证其运行结果的一致性。换句话说,用这种程序来进行测试是毫无意义的。

有兴趣可以看看它们的汇编代码,当然本质是一样的,都使用了未初始化的量。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-12 14:17:44 | 显示全部楼层
pthread_join函数确实有undefined的行为,但那是指多个线程同时对某个线程调用pthread_join函数的时候。

pthread_join函数的说明里明确指出:
如果找不到参数里线程ID对应的那个线程,该函数将返回错误码ESRCH。

ERRORS
       The pthread_join() function shall fail if:
       ......
       ESRCH  No  thread could be found corresponding to that specified by the
              given thread ID.

我未初始化thread,和将thread随便初始化成一个不存在的线程ID,其效果是一样的。
并且,-O2编译的结果就正确反应了这种现象:
error 3: No such process

所以,楼上说,这是未定义的行为,本人不敢苟同。

另外,楼上兄弟得到的结果为:
error 22: Invalid argument

这也让我感到奇怪。
我这里运行getconf GNU_LIBPTHREAD_VERSION,得到的是
NPTL 2.6

能否告知你使用的版本查看结果?
回复 支持 反对

使用道具 举报

发表于 2007-7-12 14:59:36 | 显示全部楼层
用debian gcc4.1.2编译。
#gcc pthread_error.c -O0 -o pthread_error1 -lpthread
#gcc pthread_error.c -O2 -o pthread_error2 -lpthread
在cetos4.4 NPTL 2.3.4上得到了跟楼主相反的结果。
有优化的断错,没有优化的结果才正确。
只能说明一个结果,编译器对这样代码产生的结果是不可预期的。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表