Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GCC程序集代码生成错误和解决方法_C++_Gcc_Assembly_Code Generation - Fatal编程技术网

C++ GCC程序集代码生成错误和解决方法

C++ GCC程序集代码生成错误和解决方法,c++,gcc,assembly,code-generation,C++,Gcc,Assembly,Code Generation,GCC4.5.2(在Ubuntu11.10x64上,但编译为32位)生成了无效的汇编代码,我很好奇是否可以在不更改代码的情况下进行修复,只需应用选项或类似的东西。请注意,优化已经是-O0 我有两个职能: inline long Class::Get() { long v = *(long*)(m_p); m_p += 4; return v; } inline void Class::Command() { m_p += Get(); } GCC 4.5.2生成

GCC4.5.2(在Ubuntu11.10x64上,但编译为32位)生成了无效的汇编代码,我很好奇是否可以在不更改代码的情况下进行修复,只需应用选项或类似的东西。请注意,优化已经是-O0

我有两个职能:

inline long Class::Get()
{
    long v = *(long*)(m_p);
    m_p += 4;
    return v;
}
inline void Class::Command()
{
    m_p += Get();
}
GCC 4.5.2生成此装配代码:

 9840       m_p += Get();
f689eff5:   mov 0x8(%ebp),%eax
f689eff8:   mov 0xd4(%eax),%eax
f689effe:   mov %eax,%esi
f689f000:   mov 0x8(%ebp),%eax
f689f003:   mov %eax,(%esp)
f689f006:   call 0xf66116a0
f689f00b:   lea (%esi,%eax,1),%edx
f689f00e:   mov 0x8(%ebp),%eax
f689f011:   mov %edx,0xd4(%eax)
如您所见,它将m_p值存储在%esi中,然后使用lea将返回值添加到它但是::Get()也会改变m\p!GCC似乎没有意识到这一点。因此,错误m_p是不正确的(比预期的少4个字节),因为%esi中的值已过时

我可以用电脑修理它

inline void Class::Command()
{
    long v = Get();
    m_p += v;
}

但是我只是想知道我是否可以在不改变代码的情况下应用一些pragma或smth来消除bug。至于gcc版本,我只能使用给定的版本。

这不是一个bug。如你所知,
m_p+=Get()
实际上是
m_p=m_p+Get()。编译器可以自由选择加法的求值顺序。因此,获取
m_p
,然后执行
Get()
,然后进行添加是有效的,并创建您刚刚发布的代码


第二个示例不同,因为您创建了一个新的序列点。在这种情况下,总是首先计算
Get()

您没有得到关于
long v=*(long*)(m\p)的警告吗?我相信这是双关语,从技术上讲是UB?如果要编写这样的不安全代码,可以尝试
-fn不使用严格的别名
?不,警告已关闭。但我看不出这有什么关系。我不是这样写代码的,我只是在使用它。“警告关闭了”???你觉得这是个好主意吗?不,我觉得不是个好主意。只有在极少数情况下才更改现有代码的限制都没有。@PaulR:除非
m_p
char*
,否则这是UB。这是别名规则所允许的(C
memcpy
工作所必需的)。考虑到
m_p+=4
可能就是这样。嗯,至少这看起来是更改代码的一个很好的理由,比“gcc bug”要好得多,谢谢。我认为您不会从计算顺序中得到未定义的行为。那只是个未知数。当然,您描述的顺序是一个可能的顺序,并解释了GCC结果。