请考虑以下代码:
#include <iostream>
struct foo
{
// (a):
void bar() { std::cout << "gman was here" << std::endl; }
// (b):
void baz() { x = 5; }
int x;
};
int main()
{
foo* f = 0;
f->bar(); // (a)
f->baz(); // (b)
}
Run Code Online (Sandbox Code Playgroud)
我们期望(b)崩溃,因为x空指针没有相应的成员.在实践中,(a)不会崩溃,因为this从不使用指针.
因为(b)取消引用this指针((*this).x = 5;),并且this为null,程序进入未定义的行为,因为取消引用null总是被称为未定义的行为.
会(a)导致未定义的行为吗?如果两个函数(和x)都是静态的呢?
c++ standards-compliance null-pointer undefined-behavior language-lawyer
这是一个小测试程序:
#include <iostream>
class Test
{
public:
static void DoCrash(){ std::cout<< "TEST IT!"<< std::endl; }
};
int main()
{
Test k;
k.DoCrash(); // calling a static method like a member method...
std::system("pause");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在VS2008 + SP1(vc9)上编译很好:控制台只显示"TEST IT!".
据我所知,不应该在instanced对象上调用静态成员方法.
灵感来自这个问题.
struct E {};
E e;
E f(e); // Accesses e?
Run Code Online (Sandbox Code Playgroud)
要访问是
读取或修改对象的值
空类具有隐式定义的复制构造函数
非联合类的隐式定义的复制/移动构造函数
X执行其基础和成员的成员复制/移动.[...]初始化顺序与用户定义构造函数中基数和成员的初始化顺序相同.让我们x为构造函数的任何参数,或者对于移动构造函数,x值指的是参数.以适合其类型的方式复制/移动每个基本或非静态数据成员:
- [...]基础或成员使用相应的基础或成员进行直接初始化
x.
class Foo {
public:
static const int kType = 42;
};
void Func() {
Foo *bar = NULL;
int x = bar->kType;
putc(x, stderr);
}
Run Code Online (Sandbox Code Playgroud)
这是定义的行为吗?我阅读了C++标准但是找不到任何关于访问静态const值的内容......我已经检查了GCC 4.2,Clang ++和Visual Studio 2010生成的程序集,并且它们都没有执行NULL的解引用指针,但我想确定.
我正在阅读一篇关于nullptrC++ 中一些特性的文章,一个特定的例子在我的理解中引起了一些混乱。
考虑(来自上述帖子的简化示例):
struct A {
void non_static_mem_fn() {}
static void static_mem_fn() {}
};
A* p{nullptr};
/*1*/ *p;
/*6*/ p->non_static_mem_fn();
/*7*/ p->static_mem_fn();
Run Code Online (Sandbox Code Playgroud)
根据作者的说法/*1*/,取消引用 the 的表达式nullptr本身不会导致未定义的行为。与/*7*/使用nullptr-object 调用静态函数的表达式相同。
理由基于C++ Standard Core Language Closed Issues, Revision 100中的issue 315
...
*pis not an error whenpis null 除非左值被转换为右值(7.1 [conv.lval]),它不在这里。
从而区分/*6*/和/*7*/。
因此,对实际的间接引用nullptr 不是未定义行为(在SO答案,在C ++标准的问题232讨论,...)。因此,/*1*/在这个假设下, 的有效性是可以理解的。
但是,如何 …
c++ static-methods null-pointer undefined-behavior language-lawyer
我一直都知道标准规定解除引用null是UB 的事实.然而,
p = 0;*P; 本质上不是一个错误.
并提供链接
当p为null时,*p不是错误,除非将左值转换为左值
(我认为这是一个错字,可能应该读取左值转换为右值)
Link 1也说
char*p = 0; char*q =&*(p)
是"未定义",我只能阅读定义明确或至少是实现定义
语言律师可以提供有关正在发生的事情的权威解释吗?
&((T*)NULL)->member我从研究“ UB 是 C 语言吗?”这个问题开始。这是我教科书中的一个例子,它介绍了offsetof.
我知道offsetof现在无法在 C++ 中实现(通过 cppreference 页面)。
但在阅读了一些 C++ CWS 问题后,我的问题有点变成“取消引用空指针 UB 吗?”。
另外,我认为他们不会无缘无故地改变C 中offsetoffrom的实现&((T*)NULL)->member,但我不知道为什么,也许是因为它是 UB?但我在C中没有找到一个术语说&((T*)NULL)->member是UB。对于C++,如果不是标准布局类型,我认为它是UB。
一开始,我以为会有一个明确指定的术语,比如“取消引用 NULL 指针是 UB”
,但是,随着我深入研究,我发现它比我想象的要复杂。
看了很多stackoverflow的文章回复,发现答案并不统一。
有些帖子说它是明确定义的,有些帖子说它是UB,有些帖子说它未指定。
对于那些说它定义明确的帖子,他们引用“ CWG issues #232 ”和“ CWG issues #315 ”作为原因,就像c++ access static Members using null pointer中的答案一样 。
对于那些说未指定的帖子,他们说标准中没有明确指定。
对于那些说这是UB的帖子,他们说这个问题还没有包含在标准中,所以它仍然是UB。此外,他们还给出了“如果为指针分配了无效值,则一元运算符的行为*未定义”的术语。
上面 stackoverflow 中的例子是:
#include <iostream>
class demo {
public:
static void fun()
{
std::cout << "fun() is called\n";
}
static int …Run Code Online (Sandbox Code Playgroud) 此问题的后续问题
我们有以下代码:
#include <iostream>
struct A
{
static int n;
};
int A::n = 5;
int main()
{
A* a; //uninitialized on purpose
std::cout << a->n; //UB?
}
Run Code Online (Sandbox Code Playgroud)
这样的访问是否为未定义行为?一方面,不需要对象来访问静态类成员,另一方面,operator->在未初始化的指针正在请求麻烦的情况下。
注意:GCC和MSVC会在没有任何警告的情况下编译此代码,Clang抱怨未初始化的用法。https://godbolt.org/z/Gy5fR2
我想测试我为嵌入式系统编写的异常处理程序函数,并想编写一个测试代码来注入对禁止的内存的访问。
void Test_Mem_exception
{
__asm(
"LDR R0, =0xA0100000\n\t"
"MOV R1, 0x77777777\n\t"
"STR R1, [R0,#0]"
);
Run Code Online (Sandbox Code Playgroud)
这是我想在 0xA010000 处写入访问内存位置的代码。不知何故,这对我来说似乎不是一个通用的测试代码。
是否有用 C 或 C++ 编写此类测试代码的标准方法。通用我的意思是一个独立于它运行的系统的内存映射的代码。
class Foo {
public:
static const int BAR = 2;
};
typedef Foo T1;
typedef Foo* T2;
int value1 = T1::BAR; // This works.
int value2 = T2::BAR; // This doesn't work.
Run Code Online (Sandbox Code Playgroud)
可以BAR从中提取的值T2吗?
我正在使用 c++-11。
我想这将是不好的做法,但我很好奇是否可以做到。
这里出现了一个问题,当一个指针变得晃来晃去时,问"为什么这个工作".答案是它是UB,这意味着它可能起作用.
我在一个教程中学到了:
#include <iostream>
struct Foo
{
int member;
void function() { std::cout << "hello";}
};
int main()
{
Foo* fooObj = nullptr;
fooObj->member = 5; // This will cause a read access violation but...
fooObj->function(); // Because this doesn't refer to any memory specific to
// the Foo object, and doesn't touch any of its members
// It will work.
}
Run Code Online (Sandbox Code Playgroud)
这相当于:
static void function(Foo* fooObj) // Foo* essentially being the "this" pointer
{
std::cout << "Hello";
// Foo …Run Code Online (Sandbox Code Playgroud)