读取内存时会出现分段错误吗?

3
我认为读取内存不应该造成任何问题,例如:
char *d="";
char *d2="test";
memcmp(d,d2,10);

memcmp() 能否失败?


memcmp(0,0,10) 会导致段错误...它假设指针参数指向程序中有效的内存。 - amdn
1
@amdn,我不确定“will”,因为行为有些未定义。 - s.bandara
1
@amdn:“但我知道的每个系统都会出现故障”-我非常怀疑...只要它能够读取d2后面的下5个字节,它就可以完成比较,因此,如果内存保护是按页面大小排列的,并且页面足够大以容纳两个字符串文字,它就不会出现故障,如果程序中其他地方还有合法可读数据被打包在d2后面的5个字节中,它也不会出现故障。 - Tony Delroy
int main(int argc, char* argv[]) { return memcmp(argv[1],argv[2],1); } 在调用时如果命令行参数少于两个(argc < 3),它将在我所知道的每个系统上都会发生段错误,因为argv[argc]是一个空指针。 - amdn
1
@amdn:哦,那就好。:-)。20年前可以在许多系统上工作,但我不知道现代非嵌入式系统能否运行。 - Tony Delroy
显示剩余3条评论
1个回答

5
你的假设是不正确的,因为在未映射到进程地址空间的地址处读取内存将导致SEGV错误。特别是读取地址0(在几乎所有体系结构上),以及读取内核内存空间(如果它甚至被映射),但通常情况下,读取逻辑内存时没有映射到可读物理内存。
在你的例子中,你正在对未分配的字节运行memcmp,这是未定义行为。它可能会从堆栈或数据段读取垃圾,但你无法知道。例如,d 可能就在堆栈顶部,因此你可能会超出堆栈顶部进入未映射的内存(堆栈通常向下增长)。

从堆栈或数据段读取垃圾“d”可能位于堆栈的顶部 - d本身在哪里并不重要,因为memcmp()从存储在d中的地址中读取,这是危险的。 我们知道已将其设置为字符串文字,该文字永远不会在堆栈上出现-传统上它位于数据段中。 - Tony Delroy
“d”的内存不会像Tony所说的那样分配在函数堆栈上,而是分配在只读区域吗? - Zxcv Mnb
d 是一个指针(char *),所以 d 本身不是只读的。由 d 指向的数据可能位于只读内存中,也可能位于可写区域中;您无法保证其位置或可写性,并且没有任何防止编译器将其(例如)放在堆栈顶部的措施。重点是超出它的读取是未定义的。 - abligh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接