关于GCC8.2.0编译器中的量子力学成分
  • 板块学术版
  • 楼主linfourxu
  • 当前回复55
  • 已保存回复55
  • 发布时间2021/6/18 21:14
  • 上次更新2023/11/4 21:45:14
查看原帖
关于GCC8.2.0编译器中的量子力学成分
50477
linfourxu楼主2021/6/18 21:14

前言:这是一个集全机房之力都找不到问题的UB

触发这个UB的条件:

1.使用一个GCC 8.2.0/8.1.0 (目前我能找到的编译器中这两个会触发,没有测试8.2.0以下除8.1.0以外其他版本)

2.测试如下代码

(这份代码是没有输入的,所以如果大家有类似校内题库的东西,可以往上面提交并查看结果)



#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
const int maxn=1e5+10;
const int Mod=1e9+7;
struct Node{
	int a[10][10];
	Node(){
		memset(a,0,4*100);
	}
	inline friend Node operator * (const Node &a,const Node &b){
		Node c;
		for(int i=0;i<=9;i++)
			for(int j=0;j<=9;j++){
				for(int k=0;k<=9;k++)
					c.a[i][j]=(c.a[i][j]+1ll*a.a[i][k]*b.a[k][j])%Mod;
			}
		return c;
	}
};
char s[maxn];
int p1;
Node whn[110],nown[maxn];
int p2;
Node getn(int x){
	Node a;
	for(int i=0;i<=9;i++){
		if(i==0)
			a.a[i][x]=1;
		else if(i==x){
			a.a[i][x]=2;
			a.a[i][0]=Mod-1;
		}
		else
			a.a[i][i]=1;
	}
	return a;
}
Node tmp;

int main(){
	s[1]='c';
	s[2]='a';
	s[3]='e';
	s[4]='b';
	s[5]=s[6]=s[8]='g';
	s[7]=s[9]='f';
	int n=9;
	for(int i=0;i<=9;i++)
		nown[0].a[i][i]=1;
	for(int i=1;i<=9;i++)
		whn[i]=getn(i);
	int ans=0;
	for(int i=1;i<=8;i++)
	{
		nown[i]=nown[i-1]*whn[s[i]-'a'+1];
		if(i<=1)
		{
			for(int j=0;j<=9;j++)
				for(int k=0;k<=9;k++)
					ans+=nown[1].a[j][k];
		}
	}
	const int ttt=ans;
	tmp=nown[0]*whn[3];
	//nown[1]=tmp;
	for(int j=0;j<=9;j++,printf("\n"))
		for(int k=0;k<=9;k++)
			printf("%d ",nown[1].a[j][k]);
	//fprintf(stderr,"%d\n",ttt); 这句话加不加会使上面矩阵的输出不一样
    return 0;
}

3.目前已知的能使该程序保持稳定的方法

1.将构造函数中的memset变成for循环赋值

2.将operator中从const Node &a,const Node &b变成const Node a,const Node b

3.以任何形式尝试获取“输出不确定的矩阵”的信息,如在上面代码中使用了求和的方式间接输出,当然直接输出更是不行的(这里不行是指会使答案变为稳定值)(PS:这里你观测他,他的值就确定是不是跟量子力学有些相似?)

如果有人能解释这个UB的原因,感激不尽!!

2021/6/18 21:14
加载中...