Assembly 检查公共函数中的地址参数是否为NULL

Assembly 检查公共函数中的地址参数是否为NULL,assembly,x86-64,undefined-behavior,Assembly,X86 64,Undefined Behavior,我正在创建我的onw strlen函数,它将是一个公共函数,用于x64 现在我有一个关于向这个函数传递字符串地址的问题。。。此函数使用RAX寄存器获取字符串地址。。。现在我想知道是否真的需要检查提供的地址是否等于NULL(0)?因为字符串地址可以是任何内容,即使提供的地址无效,也会发生崩溃!实际上,在函数的顶部不需要这样做: test rax, rax ; string-address == 0 (NULL) ? jz .ret0 那么在公共函数中,是否真的需要检查提供的地址

我正在创建我的onw strlen函数,它将是一个公共函数,用于x64


现在我有一个关于向这个函数传递字符串地址的问题。。。此函数使用RAX寄存器获取字符串地址。。。现在我想知道是否真的需要检查提供的地址是否等于NULL(0)?因为字符串地址可以是任何内容,即使提供的地址无效,也会发生崩溃!实际上,在函数的顶部不需要这样做:

test rax, rax        ; string-address == 0 (NULL) ?
jz   .ret0

那么在公共函数中,是否真的需要检查提供的地址是否等于0?因为我认为这是一个额外的动作!!!!(即使是公共职能部门)

这取决于您的职能部门应做什么:

在许多API中,传递
NULL
指针会有一定的效果。例如,如果传递了
NULL
指针,则希望函数返回
-1

在这种情况下,您必须添加该支票

也许您在操作系统上运行程序,其中地址
0
是有效地址。(使用现代OSs时并非如此,但在旧的(1996年)Linux版本中可能是如此)

在这种情况下,如果字符串的第一个字符存储在地址
0
中,则您的
strlen()
实现也将起作用

这意味着您不能在这种情况下添加该检查。

使用空指针调用标准函数
strlen
,这是未定义的行为。这并不要求/保证崩溃,只是意味着这是可能的。(从你鼻子里飞出来的恶魔也是如此)。UB的字面意思是任何事情都可能发生(不违反标准)

显然,在实践中,实际发生的事情通常没有那么多,当然,大多数操作系统甚至不允许您映射零页面。(大多数C/C++实现使用位模式
0
作为
nullptr
/NULL的对象表示,与C/C++源代码级
0
相同,尽管这不是必需的。)

因此,大多数strlen实现只是从加载第一个字节开始。(或者,如果它不会跨页,请加载前16个字节,以便使用SSE2无分支地检查零。对glibc的x86-64 asm strlen实现进行了一些讨论。)

如果调用方希望避免空指针崩溃,请在调用前检查

在编写函数时不使用
nullptr
检查是完全有效的,
只要合同的这一部分对编写调用它的代码的人是明确的

如果您是在asm中手工编写的(可能是出于性能原因),那么您应该避免编写不需要的额外的健全性检查,除非有一些有用的行为,您实际上可以从几个调用方中提取出来,并将其写入strlen的包装器中。(例如,对于非NULL,它属于正常的未检查strlen,因此它只是在正常strlen标签之前的一对额外指令。)


此外,对于空输入,您可以返回哪些对调用方有用的内容
0
意味着阅读
ptr[0]
并找到
'\0'
是安全的。也许对一些打电话的人来说没问题。SIZEZT是一个无符号类型,所以每个其他可能的值都是肯定的,也是一个有效的大小。

请先考虑一下你之前的问题,然后再问一个新的问题。你只是让那些试图帮助你的人束手无策。你所说的“公共职能”是什么意思?C标准提供的许多函数在传递nullptr(包括
strlen
-->)时具有未定义的行为。“是否确实需要检查提供的地址是否等于0”您对必需的定义是什么?“我想问的是,只检查地址的低32位就足够了,还是检查整个64位很重要?“让我们把你的问题带到逻辑的极端:为什么不检查低8位
测试al,al
,或者甚至是最低位。谢谢你的回答。。。在最现代的软件中,程序员知道他的地址是有效的,因为他在循环中检查地址。。。所以我认为另一个检查级别是一个额外的动作。。。因为我们只是检查一个地址是否等于0!!!提供的地址甚至可能是错误的地址,因此我们无法检查!!!!所以仍然会有一个问题,检查0是额外的(我认为正如我所说的(原因))