我正在使用一些在Solaris10上运行的古老的遗留代码。在旧的服务器上,代码编译和运行没有任何问题。
然后,代码被迁移到Solaris11服务器上,在那里代码仍然可以编译,但当它运行时,它会创建一个seg故障核心转储。
在这两种情况下,使用的编译器都是/opt/SUNWspro/bin/cc。
以下是代码片段:
#include <stdio.h>
char *blank = " ";
main(argc,argv)
int argc;
char **argv;
{
blank[35] = '\0';
printf("Success.\n");
}这在Solaris10上有效,但在Solaris11上导致了段故障(核心转储)。通常我会说,段故障是由于在blank[]数组仅上升到空白34时尝试写入blank35而导致的,除非此代码在Solaris10上有效。
此外,当我在新服务器上将行更改为'blank34 = '\0';‘时,我仍然得到一个段故障核心转储。
当我将空白改为普通数组时(同时也现代化了main),一切正常,正如我所期望的那样:
#include <stdio.h>
char blank[35];
int main(int argc,char **argv)
{
int i;
for (i=0; i<34; i++)
{
blank[i] = ' ';
}
blank[34] = '\0';
printf("Success.\n");
return 0;
}我真正需要知道的是为什么这段代码可以在旧服务器上正常运行,以及我忽略了什么?我可以将代码更改为使用普通数组,使其在新服务器上运行,但这会导致什么类型的问题?
发布于 2020-05-01 23:24:12
它们使用的是完全相同的C编译器版本和完全相同的标志吗?
较早版本的Studio编译器(/opt/SUNWspro/...)默认情况下,将常量字符串放入可写内存中,除非您使用-features=conststrings标志将它们放入只读内存中。
如https://docs.oracle.com/cd/E77782_01/html/E77788/bjapr.html#OSSCGbjaqo上的Studio12.6文档所示,后来的Studio编译器版本将-features=conststrings设置为默认版本,并要求-features=no%conststrings再次将其设置为可写的。
这类似于gcc对等效标志-fwritable-strings所做的操作,该标志在最早的版本中默认处于打开状态,然后在removed in gcc 4.0之前的几个版本中被默认关闭,从而使常量字符串始终在只读内存中。
发布于 2020-05-01 04:03:00
请注意,您没有char blank[],而是指向字符串文字的char *blank。字符串文字是不可变的。此代码试图修改blank指向的文字的一个字符,从而导致未定义的行为。关于未定义的行为的有趣之处在于,它可以做任何事情,包括按您想要的方式执行函数。
同样值得注意的是,字符串文字已经隐式地以null结尾,因此在末尾显式添加'\0‘是不必要的。
发布于 2020-05-01 04:48:57
最有可能的是,问题不在于操作系统版本,而在于构建代码时所使用的编译器。这段代码有很多问题,很容易看出它如何在一个编译器上工作,而不是在另一个编译器上工作。考虑到我们不知道您使用的是什么编译器,我不会去推测。
但我敢跟你打赌,如果这两台机器都有相同的硬件架构(例如,两者都是ultrasparc),那么如果你在Solaris10上编译你的二进制文件,那么它在Solaris11上就会运行得很好。
https://stackoverflow.com/questions/61531694
复制相似问题