这有点啰嗦,所以这是快速版本:
为什么这会导致运行时TypeLoadException?(并且编译器是否应该阻止我这样做?)
interface I
{
void Foo<T>();
}
class C<T1>
{
public void Foo<T2>() where T2 : T1 { }
}
class D : C<System.Object>, I { }
Run Code Online (Sandbox Code Playgroud)
如果您尝试实例化D,则会发生异常.
更长,更具探索性的版本:
考虑:
interface I
{
void Foo<T>();
}
class C<T1>
{
public void Foo<T2>() where T2 : T1 { }
}
class some_other_class { }
class D : C<some_other_class>, I { } // compiler error CS0425
Run Code Online (Sandbox Code Playgroud)
这是非法的,因为类型约束C.Foo()与那些不匹配I.Foo().它会生成编译器错误CS0425.
但我想我可能会违反规则:
class D : C<System.Object>, I { } // …Run Code Online (Sandbox Code Playgroud) 我遇到了使用Visual Stuido 2010 SP1,cl.exe版本16.0.40219.1编译一些模板代码的问题
以下代码将导致编译器访问违规:
template<typename T>
class A
{
A(){}
};
template<typename T>
class B : public A<T>
{
using A::A(); // Compiler access violates
// **EDIT**
//using A<T>::A<T>; // Compiler succeeds
//using A<T>::A(); // Compiler reports error
};
int main(int argc, char* argv[])
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它会生成以下错误(除了"cl.exe已停止工作,C0000005异常):
1>d:\projects\cpptest\cpptest\cpptest.cpp(11): fatal error C1001: An internal error has occurred in the compiler.
1> (compiler file 'msc1.cpp', line 1420)
1> To work around this problem, try simplifying or changing the program …Run Code Online (Sandbox Code Playgroud) 在过去的几天里,我一直在调试一个涉及C++中lambdas的奇怪问题.我已将问题减少到以下症状:
this指针被破坏拉姆达内(注:this总是被复制捕获,因此拉姆达应该得到自己的this指针,它指向的App对象)std::coutprint语句时发生,并在创建lambda之前调用.print语句看似完全不相关(例如print"Hello!").printf()也表现出相同的行为.x86体系结构编译器编译并运行良好(参见示例).App对象内保存指向它的指针),则不会发生错误.-O0标志),则不会发生错误.它在优化设置为时发生-O2.以下是我能想出的最简单,可编译的代码示例,它会导致问题.
#include <iostream>
#include <functional>
class App {
public:
std::function<void*()> test_;
void Run() {
// Enable this line, ERROR is printed
// Disable this line, app runs o.k.
std::cout << "This print statement causes the bug below!" << std::endl;
test_ = [this] () …Run Code Online (Sandbox Code Playgroud) Consider the following code:
template <typename T> int foo();
template <typename T> int foo() = delete;
Run Code Online (Sandbox Code Playgroud)
is this valid C++11?
... see it all on GodBolt.
so which compilers are right and which compilers are s@#$%e ? :-)
我注意到gcc 5.0拒绝以下代码,而clang 3.6接受它.
template<int n>
struct I
{
typedef int Type;
};
template<typename T>
struct A
{
typedef I<sizeof(sizeof(T))>::Type Type;
};
Run Code Online (Sandbox Code Playgroud)
两个编译器似乎在sizeof(sizeof(T))类型依赖或依赖于值的表达式上有所不同.如果表达式是依赖的,那么它I<sizeof(sizeof(T))>是一个依赖类型,这意味着typename应该是必需的.
这由C++ 11标准中的以下措辞涵盖:
[temp.dep.type]/8
如果是,则类型依赖于
- 一个simple-template-id,其中模板名称是模板参数或任何模板参数是依赖类型或依赖于类型或依赖于值的表达式
[temp.dep.expr/4
以下表单的表达式从不依赖于类型(因为表达式的类型不能依赖):
Run Code Online (Sandbox Code Playgroud)sizeof unary-expression sizeof ( type-id )[temp.dep.constexpr]/2
如果unary-expression或expression是typedependent或type-id是依赖的,则以下形式的表达式是值依赖的:
Run Code Online (Sandbox Code Playgroud)sizeof unary-expression sizeof ( type-id )
我的解释是,sizeof(T)永远不能依赖于类型,意味着sizeof(sizeof(T))永远不能依赖于类型或依赖于价值.
这是gcc中的错误吗?
代码:
#define OPPOSITE(c) (*((typeof(x) *)&(x)))
int foo(volatile int x)
{
OPPOSITE(x) = OPPOSITE(x) + OPPOSITE(x);
return x;
}
int bar(volatile int x)
{
OPPOSITE(x) = OPPOSITE(x) + OPPOSITE(x);
return x;
}
Run Code Online (Sandbox Code Playgroud)
结果(-Os):
foo:
mov DWORD PTR [rsp-4], edi
mov eax, DWORD PTR [rsp-4]
mov edx, DWORD PTR [rsp-4]
add eax, edx
mov DWORD PTR [rsp-4], eax
mov eax, DWORD PTR [rsp-4]
ret
bar:
mov DWORD PTR [rsp-4], edi
mov eax, DWORD PTR [rsp-4]
add eax, eax
ret
Run Code Online (Sandbox Code Playgroud)
或ARM gcc。( -O3 …
我已经调试了一段时间的程序,最终发现错误是由于引用没有像我想象的那样更新.
这是一个显示我遇到的问题的示例:
#include <iostream>
using namespace std;
struct Test {
Test& set(int& i){ i = 10; return *this; }
Test& print(const int& i){ cout << i << endl; return *this; }
};
int main(void){
int i = 0;
Test t;
t.set(i).print(i + 5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我曾预料到这里的print()方法会输出15,但输出5.
编辑:10天后我才意识到,用clang输出15!这是GCC中的错误吗?
我正在研究关于预处理器的确切行为的C++标准(我需要实现某种类型的C++预处理器).根据我的理解,我在下面编写的示例(以帮助我的理解)应该是有效的:
#define dds(x) f(x,
#define f(a,b) a+b
dds(eoe)
su)
Run Code Online (Sandbox Code Playgroud)
我希望像宏调用这样的第一个函数dds(eoe)被替换为f(eoe,(注意替换字符串中的逗号),然后f(eoe,su)在重新扫描输入时将其视为.
但VC++ 2010测试给了我这个(我告诉VC++输出预处理文件):
eoe+et_leoe+et_l
su)
Run Code Online (Sandbox Code Playgroud)
这是违反直觉的,显然是不正确的.它是VC++ 2010的一个错误还是我对C++标准的误解?特别是,像我一样在替换字符串的末尾添加逗号是不正确的吗?我对C++标准语法的理解是,任何preprocessing-token人都可以在那里使用.
编辑:
我没有GCC或其他版本的VC++.有人可以帮我验证这些编译器.
考虑以下代码:
void MemMove8(void* dst, void* src)
{
char tmp[8];
memcpy(tmp, src, 8);
memcpy(dst, tmp, 8);
}
Run Code Online (Sandbox Code Playgroud)
MSVC (16.7.1) x86 with /O2 为此函数生成以下程序集:
; _dst$ = ecx
; _src$ = edx
mov eax, DWORD PTR [edx]
mov DWORD PTR [ecx], eax
mov eax, DWORD PTR [edx+4]
mov DWORD PTR [ecx+4], eax
Run Code Online (Sandbox Code Playgroud)
但如果输入和输出缓冲区重叠,这将不起作用(在某些情况下)。
生成的代码对我来说似乎是错误的;或者这是一个有效的转换,我在这里遗漏了什么?
我正在运行一个提供服务的 C++ 程序,并注意到即使不提供任何请求,它也会占用 100% 的 CPU。我将问题缩小到一个 while 循环,该循环调用std::sleep_for以防止服务退出。
为了测试,我编译并运行了这个简单的测试程序:
#include <chrono>
#include <thread>
int main(int argc, char * argv[])
{
std::this_thread::sleep_for(std::chrono::hours::max());
}
Run Code Online (Sandbox Code Playgroud)
我的预期是它会休眠很长时间,事实上,当我在 M1 Mac 上尝试它时,我看到了预期的行为。然而,当我在 Redhat Linux 8 机器上运行它时,它立即返回。我还在 Mac 上运行的 Rocky Linux 8 docker 容器上进行了尝试,这也立即返回。这证实了这种情况通常发生在 RHEL 8 系统上 - 或者至少在 gcc 8.5.0 上发生,因为两个 Linux 系统上的编译器版本是相同的(Mac 上的编译器是 Apple 提供的 clang)。
这解释了为什么我的服务占用了 100% 的 CPU,因为它是在 while 循环中调用的。但我从未听说过这种行为。还有其他人吗?
当然,我可以通过睡一会儿来轻松解决问题std::chrono::seconds(1)。我只是出于求知欲才问这个问题。
compiler-bug ×10
c++ ×8
gcc ×3
visual-c++ ×3
arm ×1
c ×1
c# ×1
c++-chrono ×1
c++11 ×1
clang ×1
clr ×1
generics ×1
lambda ×1
linux ×1
memcpy ×1
nvcc ×1
preprocessor ×1
runtime ×1
templates ×1
x86 ×1