请考虑以下代码:
#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
我参加了三星的采访.他们询问了很多关于程序内存布局的问题.我对此几乎一无所知.
我用Google搜索了"可执行程序的内存布局"."进程的内存布局".
我很惊讶地看到关于这些主题的信息不多.大多数结果都是论坛查询.我只是想知道为什么?
这些是我发现的几个链接:
我想从一本正确的书而不是一些网络链接中学到这一点.(兰迪海德也是一本书,但还有一本书).我可以在哪本书中找到关于这个主题的清晰和更多信息?
我也想知道,为什么操作系统书没有在他们的书中涵盖这一点?我读了第6版的摊位.它只是讨论了过程控制块.
整个布局的创建是对的任务linker
吗?我在哪里可以阅读有关此过程的更多信息 我想要从磁盘上的程序到处理器上执行的完整信息.
编辑:
最初,即使在阅读下面给出的答案后,我也不清楚.最近,我在看完这些文章之后看到了这些文章,我明白了.
帮助我理解的资源:
- www.tenouk.com/Bufferoverflowc/Bufferoverflow1b.html
- 5部分PE文件格式教程:http://win32assembly.online.fr/tutorials.html
- 优秀文章:http://www.linuxforums.org/articles/understanding-elf-using-readelf-and-objdump_125.html
- PE Explorer:http://www.heaventools.com/
是的,"可执行程序的布局(PE/ELF)"!="进程的内存布局").在第3个链接中找到自己.:)
在清除了我的概念后,我的问题让我看起来很愚蠢.:)
说我有班级:
class A
{
public:
void foo() { cout << "foo"; }
};
Run Code Online (Sandbox Code Playgroud)
并像这样调用foo:
A* a = NULL;
a->foo();
Run Code Online (Sandbox Code Playgroud)
我怀疑这会调用未定义的行为,因为它等同于(*a).foo()
(或者它是?),并且取消引用a NULL
是 UB,但我找不到引用.谁能帮我吗?还是定义了?
不,功能不是virtual
.不,我没有访问任何成员.
编辑:我投票结束这个问题,但不会删除它,因为我自己找不到副本,我怀疑这个标题可能更容易被其他人找到.
我已经向几位同事展示了这一点,没有人有解释.我碰巧遇到了这个问题,因为我认为我在代码中发现了一个错误,但是很惊讶地看到代码实际运行了.这是一个简化版本.这是用XE-2完成的.
到目前为止我与之交谈的每个人都期望应该抛出NullReferenceException.
TUnexplainable = class(TObject)
public
function Returns19: Integer;
end;
function TUnexplainable.Returns19: Integer;
begin
Result := 19;
end;
Run Code Online (Sandbox Code Playgroud)
以下测试永远不会有效,但它会成功运行.为什么没有抛出NullReferenceException ????
procedure TTestCNCStep.ShouldNeverEverWorkV4;
var
Impossible: TUnexplainable;
Int1: Integer;
begin
Impossible := nil;
Int1 := Impossible.Returns19; // A Null Reference Exception should ocurr here!!! Instead the method Returns19 is actually invoked!!!!
Check(Int1 = 19);
end;
Run Code Online (Sandbox Code Playgroud)
我不明白下面的代码如何产生给定的输出.
#include <iostream>
using namespace std;
class MyClass
{
public:
void doSomething()
{
cout<<"Inside doSomething"<<endl;
}
};
int main()
{
MyClass obj;
MyClass *ptr=&obj;
ptr->doSomething();
ptr=NULL;
ptr->doSomething();
}
Run Code Online (Sandbox Code Playgroud)
产量
里面doSomething
里面做的东西
我用空指针执行了一个函数,它实际上调用了该函数.使用ptr的cout检索存储在ptr中的地址表明在语句ptr = NULL之后ptr被设置为0; 但是它仍然调用doSomething().内部实际发生了什么?
考虑以下代码:
int main()
{
struct EmptyStruct{
void nonstatic_mf() const { std::cout <<"EmptyStruct\n"; }
};
EmptyStruct *esptr = nullptr;
esptr->nonstatic_mf();
}
Run Code Online (Sandbox Code Playgroud)
这是一个合法的 C++(它似乎在 gcc 和 clang 中工作)?
可能重复:
访问NULL指针上的类成员
一个非常愚蠢的问题或者可能是我的概念疑问.
#include <iostream>
using namespace std;
class A
{
public:
void print()
{
cout<<"Printing\n";
}
};
int main()
{
A * a = NULL;
a->print();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:打印
如何为a
指针(即NULL)能够访问A类的成员函数
请解释......可能只是一个愚蠢的问题,但我的印象是NULL指针不会访问类的成员函数.
该计划是否:
#include <stdio.h>
struct foo
{
void blah() {printf("blah\n");}
int i;
};
void main(int, char**)
{
((foo*)NULL)->blah();
}
Run Code Online (Sandbox Code Playgroud)
blah
在你知道的任何编译器上崩溃,或者做输出以外的任何事情?当通过NULL指针调用时,任何函数是否会崩溃,如果它不访问任何成员(包括vtable)?
关于这个主题还有其他问题,例如在NULL指针上访问类成员,并且它是合法/定义良好的C++来调用不通过空指针访问成员的非静态方法吗?,并且总是指出这会导致未定义的行为.但这在现实世界中是不确定的,还是只在标准的世界中?现有的编译器是否表现不如预期?你能想到为什么未来的编译器不会按预期运行的任何合理的理由吗?
如果函数确实修改了成员,但是保护了NULL ptr.例如,
void foo::blah()
{
foo* pThis = this ? this : new foo();
pThis->i++;
}
Run Code Online (Sandbox Code Playgroud)
编辑:对于记录,我想要的原因是使我的链表类的接口尽可能简单明了.我想将列表初始化为NULL,其惯用用法如下:
pList = pList->Insert(elt);
pList = pList->Remove(elt);
...
Run Code Online (Sandbox Code Playgroud)
所有操作员返回新头元素的位置.不知怎的,我没有意识到使用容器类会让事情变得更容易,没有任何缺点.
我不懂C++中的东西 - 我在类上创建了一些指针并将其设置为null.
现在我用这个空指针调用一些函数,函数成功.为什么不崩溃?
class Entity
{
public:
void Print() const
{
std::cout << "Print" << std::endl;
}
};
int main()
{
Entity* ptr = nullptr;
Entity& _ref = *ptr; // No crash here - I expected a null pointer exception
_ref->Print();
}
Run Code Online (Sandbox Code Playgroud) 我正在寻找关于这段代码的澄清.对A :: hello()的调用有效(我期望一个segv).segfault确实通过对成员x的访问,所以看起来单独的方法解决方案实际上并没有取消引用bla?
我编译优化关闭,gcc 4.6.3.为什么不把bla->你好()爆炸?只是想知道'发生了什么事.谢谢.
class A
{
public:
int x;
A() { cout << "constructing a" << endl; }
void hello()
{
cout << "hello a" << endl;
}
};
int main()
{
A * bla;
bla = NULL;
bla->hello(); // prints "hello a"
bla->x = 5; // segfault
}
Run Code Online (Sandbox Code Playgroud) c++ ×8
pointers ×3
null ×2
assembly ×1
delphi ×1
delphi-xe2 ×1
memory ×1
methods ×1
null-pointer ×1
process ×1