c语言 - 一般保护/核心转储"boundary"



我和一个朋友讨论了一个算法,在这个算法中,我需要读取超过";变量";。

他说我总是可以安全地做这件事,但我不同意。

我知道这是未定义的行为,但说这句话的人在C方面确实很有经验。正如你在下面看到的,它确实适用于少量字节。

这是一个想法的例子,但有点像";超过顶部";。

#include <stdint.h>
#include <stdio.h>
const uint64_t a = 100;
int main(){
const char *s = (const char *) &a;
printf("%dn", s[1530]);    // this works
//  printf("%dn", s[15300]);   // this doesn't
}

访问将是只读的,我会屏蔽它,这样我就不在乎读垃圾了
实际上,我只需要变量后面的16个字节
此外,变量不需要是const,但很可能是const。

这是安全的吗,至少对少量字节来说是安全的?

你和你的朋友说话目的不一致。

未定义的行为意味着";未在标准中定义;通常是为了避免约束实现。

未定义的行为可以由特定的实现来定义,但是:

  • 不可移植到其他系统或实现
  • 不能移植到同一实现的未来版本
  • 根据实现所做的保证,它可能无论如何都得不到很好的支持

您还没有告诉我们您的平台或实现,所以我们只能说"这是未定义的行为;因为我们只有标准。

如果您的实现确实做出了一些相关的保证,您有一些特定于平台的理由相信它会继续工作。。。那么至少要记住,同样的代码在其他地方不会起作用。

如果,看起来更有可能的是,代码恰好做了正确的事情,此时,在一个特定实现的当前版本上使用当前代码。。。那么它随时都可能坏掉。

(也许我误解了你的意图,如果是这样,我只是再次删除这个答案:-(。

如果你试图从你无法访问的内存段中读取(它可能属于另一个进程(,大多数OS/CPU会向你的进程发送"段冲突"信号。这个信号通常会终止您的进程。

你可以(我想说,只是实验性的(拦截这个信号,例如:

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <stdint.h>
static /*sig*/jmp_buf segv_env;
static void * old_segv_sig;
static void segv_handler(int s) { /*sig*/longjmp(segv_env,s); } 
int safe_read_check(void * mem,size_t sz)
{
int safe;
size_t i;
int r;
safe = 0;
old_segv_sig = signal( SIGSEGV, segv_handler );
if( /*sig*/setjmp( segv_env /*,1*/ ) == 0 )
{
for( i = 0 ; i < sz ; i++)
r = ((char*)mem)[i];
// no signals
safe=1;
}
signal( SIGSEGV, old_segv_sig ); // restore signal handler
return safe;
}
const uint64_t a = 100;
int main()
{
const char *s = (const char *) &a;
if( safe_read_check( (void*)&s[153],16 ) )
printf("safen");
else
printf("unsafen");
if( safe_read_check( (void*)&s[15300000L], 16 ))
printf("safen");
else
printf("unsafen");
return 0;
}

最新更新