Visual Studio 版本:17.7.1 (MSVC 19.37.32822)
使用默认设置和编译器标志新创建的项目。
最小可重现示例:
#include <cstdio>
__declspec(noinline) void test2(char** data)
{
// After moving the pointer:
// data_1 now points to data[1] = 1
// data_0 now points to data[0] = 2
*data += 1;
}
__declspec(noinline) void test(char* data_1)
{
char* data_0 = data_1;
test2(&data_1);
int len = (int)(data_1 - data_0);
if (*data_1 & 1)
{
if (*data_0 & 2)
printf("good\n");
}
}
int main()
{
char data[2];
data[0] = 2;
data[1] = 1;
test(data); …Run Code Online (Sandbox Code Playgroud) 我定义了两个版本的函数模板,名为compare:
#include <cstring>\n\nusing namespace std;\n\n// fist version\ntemplate <size_t N, size_t M>\nint compare(const char (&a)[N], const char (&b)[M]) {\n return strcmp(a, b);\n}\n\n// second version\ntemplate <typename T>\nint compare(const T &a, const T &b) {\n if (a < b) return -1;\n if (b < a) return 1;\n return 0;\n}\n\nint main() {\n const char *p1 = "dog", *p2 = "cat";\n compare(p1, p2); // call second version\n compare("dog", "cat"); // call second version?\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n在使用c++11std的CPP Primer(第5版)一书中,作者说compare(p1, p2)将调用第二版模板,因为没有办法将指针转换为对数组的引用。将 …
我最近撕掉了我的头发调试这段代码(稍为修改以简化演示):
char *packedData;
unsigned char* indexBegin, *indexEnd;
int block, row;
// +------ bad!
// v
int cRow = std::upper_bound( indexBegin, indexEnd, row&255 ) - indexBegin - 1;
char value = *(packedData + (block + cRow) * bytesPerRow);
Run Code Online (Sandbox Code Playgroud)
当然,std::upper_bound在64位环境中将两个指针的差异(减去搜索到的数组的开头的结果)分配给int而不是ptrdiff_t是错误的,但是产生的特殊不良行为是非常意外的.当[indexBegin,indexEnd]的数组大小超过2GB时,我希望这会失败,所以差异溢出了一个int; 但实际发生的事情是当indexBegin和indexEnd在2 ^ 31的两侧有值时(即indexBegin = 0x7fffffe0,indexEnd = 0x80000010)崩溃.进一步的调查揭示了以下x86-64汇编代码(由MSVC++ 2005生成,带有优化):
; (inlined code of std::upper_bound, which leaves indexBegin in rbx,
; the result of upper_bound in r9, block at *(r12+0x28), and data at
; *(r12+0x40), immediately precedes this point)
movsxd rcx, r9d …Run Code Online (Sandbox Code Playgroud) 以下代码给出了预期的编译器错误(Demo):
1 template<bool> struct Range;
2
3 template<int value, typename = Range<true> > struct Unique;
4 template<int value> struct Unique<value, Range<(value > 1)> > { typedef char type[1]; };
5 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };
6
7 Unique<3>::type o1;
8 Unique<3>::type o2;
Run Code Online (Sandbox Code Playgroud)
现在,如果我换掉第5行和第7行.然后没有编译器错误 !! 演示.
5 Unique<3>::type o1;
7 template<int value> struct Unique<value, Range<(value > 2)> > { typedef char type[2]; };
Run Code Online (Sandbox Code Playgroud)
因为o1,没有错误(value > 2) …
c++ sfinae template-specialization language-lawyer compiler-bug
struct Line
{
Bounds bounds_;
Vector origin_;
uint32_t begin_;
uint32_t end_;
dist ascent_;
dist descent_;
};
Run Code Online (Sandbox Code Playgroud)
使用如下:
Line line = {};
while (!parser.done()) {
line = Line(); // zero-initialize
...
}
Run Code Online (Sandbox Code Playgroud)
Bounds并且Vector是非POD类,dist是一个typedef int64_t.
但是,VC++ 11的优化32位版本构建似乎line在while循环中至少留下了未初始化的部分内容.为什么?根据Do,括号后的类型名称与new有所区别?,它应该零初始化它,对吧?
我将struct成员的值记录到文件中:
Line line = {};:非POD类型默认初始化,其他类型为0.line = Line();:POD类型仍默认初始化,其他包含随机值.这是重现问题的最小(C++ 14)代码:
template <void (&a)()>
struct Foo {
static auto value() {}
};
void bar() {}
template struct Foo<Foo<bar>::value>;
Run Code Online (Sandbox Code Playgroud)
GNU C++ "g ++(Ubuntu 5.1.0-0ubuntu11~14.04.1)5.1.0"编译器发出:
error: could not convert template argument ‘Foo<a>::value<bar>’ to ‘void (&)()’
template struct Foo<Foo<bar>::value>;
^
Run Code Online (Sandbox Code Playgroud)
我注意到的第一个奇怪的事情是Foo<a>::value<bar>- a没有被替换,并且value以某种方式成为模板?
以下无意义的修复增强了我的印象,这是一个编译器错误:
value()返回void而不是推断它value:template struct Foo<*Foo<bar>::value>;value:template struct Foo<(Foo<bar>::value)>;a指针:template <void (*a)()> struct Foo ...最后,Clang编译我的片段很好.
那么,某个禁止第一个片段的地方是否有一个模糊的标准条款,或者GCC刚刚死在我身上?
我像这样使用简单的循环缓冲区
var
Values: array [byte] of single;
ptr: byte;
Run Code Online (Sandbox Code Playgroud)
在这个测试例子中
for ptr:=0 to 10 do Values[Byte(ptr-5)]:=1;
Run Code Online (Sandbox Code Playgroud)
我希望设置为1前5个值和最后5个值,但XE4 compiller产生不正确的代码,它使用32位指针数学来计算数组索引:
for ptr:=0 to 10 do Values[Byte(ptr-5)]:=1;
005B94BB C645FB00 mov byte ptr [ebp-$05],$00
005B94BF 33C0 xor eax,eax
005B94C1 8A45FB mov al,[ebp-$05]
005B94C4 C78485E0FBFFFF0000803F mov [ebp+eax*4-$0420],$3f800000
005B94CF FE45FB inc byte ptr [ebp-$05]
005B94D2 807DFB0B cmp byte ptr [ebp-$05],$0b
005B94D6 75E7 jnz $005b94bf
Run Code Online (Sandbox Code Playgroud)
这是我的错误代码和操作字节索引的正确方法吗?
我安装了最新的VS2017更新(15.4.4),在编译项目时,单元测试开始失败.在使用优化(/ O2)和浮点快速模型(/ fp:fast)时,似乎在某些情况下会出现问题.以前的编译器(VS2017更新15.2)没有发生此问题.
这是一个示例程序:
#include <iostream>
const float FACTOR = 0.01745329251994329576923690768489f;
unsigned long long hoursToMicrosecs(int hours)
{
return hours * 3600 * 1000000LL;
}
float degToRad(float deg)
{
return deg * FACTOR;
}
float f(int u1, int u2)
{
float percent = ((u1 - u2) / 1000.0f) / (hoursToMicrosecs(24) / 1000000.0f);
return degToRad(percent * 360);
}
int main()
{
auto result = f(3600000, 35063681);
std::cout << result << '\n';
return (result > -3.0f) ? 0 : -1;
}
Run Code Online (Sandbox Code Playgroud)
result 应该是-2.2881,但输出实际上是-394.868,这不仅是不准确的. …
c++ floating-point visual-c++ compiler-bug visual-studio-2017
以下C++文件:
struct Base {
template <typename T, int = 42>
void f(T &&) const {}
};
struct Derived: Base {
template <typename T, typename X = typename T::asdf>
void f(T &&) const {}
using Base::f;
};
int main() {
Derived const cd;
cd.f('x');
}
Run Code Online (Sandbox Code Playgroud)
与GCC编译良好但不与Clang编译:
$ g++-7.3.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-7.2.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-6.4.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-5.4.0 -std=c++11 test.cpp -o test -Wall -Wextra
$ g++-4.9.4 -std=c++11 …Run Code Online (Sandbox Code Playgroud) 嗨我有状态lambda表达式的问题.
这是一个虚拟的例子,但在我看来,ms编译器做错了什么,或者我有一些未定义的行为?
码:
int main() {
auto start = [x = 1, z = 1]() mutable {
goto resume;
for (; ; ++z) {
for (x = 1; x < z; ++x) {
resume:
std::cout << z;
if (z > 3)
return 1;
}
}
};
start();
}
Run Code Online (Sandbox Code Playgroud)
Microsoft编译器版本19.16.27024.1
cl -O2/std:c ++ 17(或-O1,-Ox)----->打印'1'然后打印无限数'2'(错误我认为)
cl -Od/std:c ++ 17 ----->打印12334
g ++(Ubuntu 7.3.0-27ubuntu1~18.04)7.3.0
g ++ -03 ----->打印12334
clang version 8.0.0(trunk)clang ++ -O3 ----->打印12334
https://godbolt.org/z/wsHYA-(代码但没有std :: cout)
删除for循环后(这个带有x变量)问题不再可见; 如果somone想知道我为什么编写这样的代码 - 我想模仿协同程序等的行为(没有什么严重的,例如序列生成器)