请考虑此代码段(为简洁起见,简化语法)。
void simple (char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
我的导师说 MyArray 最多可以复制来自 bar 的12个元素,但是从我的#&# 39;我读过,MyArray只能存储11个字符,因为它最后需要空字符。因此,如果 bar 的接收值为12或更大,则会发生缓冲区溢出。我的导师说,只有收到的 bar 值才会发生这种情况 是13或更高。谁对吗?如果你能引用一个可靠的消息来源我会说服他。我很感激。
答案 0 :(得分:4)
定义char
创建一个12 char [12]
的数组,可用于存储字符串。由于C中的字符串是空终止的,因此其中一个字符需要能够在字符串的末尾存储空字节。
因此strcpy
类型的变量可以包含最多11个字符的字符串。尝试使用strncpy
复制长度为12或更长的字符串,如示例所示,将溢出数组的边界。
如果您使用strncpy(MyArray, bar, 12);
,如下所示:
MyArray
这不会溢出缓冲区,因为它最多可复制12个字符。但是,如果复制了12个字符,则表示该字符串不是以空值终止的,因此在技术上不是字符串。然后尝试在$HOME/.aws/config
上使用期望空终止字符串的任何其他字符串函数将读取数组的末尾。
答案 1 :(得分:0)
这很难说,因为你的问题措辞有些令人困惑,但我认为你是对的,而你的导师是错的。
给出代码
void simple(char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
如果传入的bar
指向一个包含11个或更少字符的字符串,则有效字符串将被复制到MyArray
,没有缓冲区溢出。但是如果字符串长度为12(或更多)字符,那么就会有缓冲区溢出,因为strcpy
也会复制第13个字符,终止空字符。
之前您曾问过strncpy
。鉴于代码
void simple2(char *bar) {
char MyArray[12];
strncpy(MyArray, bar, 12);
}
如果传入的bar
指向11个或更少字符的字符串,则有效字符串将被复制到MyArray
。但如果字符串长度为12个字符,我们就会遇到不同的问题。 strncpy
将复制12个字符并停止,这意味着它不会复制终止空字符。不存在缓冲区溢出,但MyArray
仍然不会包含有效字符串。
另外,你要求一个可靠的来源。我写了C FAQ list - 你认为这可信吗? : - )
答案 2 :(得分:0)
我的导师说MyArray最多可以复制来自栏的12个元素
更准确地说,数组MyArray
最多可容纳数组bar
的12个元素。否则将尝试访问阵列之外的内存。
所以事实上你的导师是对的。
声明数组MyArray
只有12个元素
char MyArray[12];
但是从我读过的内容来看,MyArray只能存储11个字符,因为 它最后需要空字符
终止零也是一个角色。函数strcpy
复制源字符串中的所有字符,包括源字符串中存在的终止零。
因此,如果bar的接收值为12或更大,则缓冲区溢出 会发生
在这种情况下,神奇数字12意味着什么?它是数组bar
中的字符数,还是存储在数组栏中的字符串的长度(用作参数的转换为指向其第一个元素的指针)?
如果数字12表示存储在数组bar
中的字符串的大小,则函数strcpy
将尝试复制数组的所有字符,包括终止零,在本例中为数组{ {1}}必须声明为有13个元素。
MyArray
但是,如果数字12表示数组char MyArray[13];
中的元素数(用作函数的参数)并且它包含一个字符串,那么字符串的长度显然小于12.所以数组MyArray可以接受源数组的所有字符,包括终止零。
所以混淆的原因是你没有得出一个共同的结论,数字12表示它是源字符串的长度还是源数组的大小。
在第一种情况下,确实存在未定义的行为。
在第二种情况下,如果源数组包含一个字符串,那么代码将是格式良好的。
答案 3 :(得分:0)
正确使用strncpy将是:
options
这只是输入一个终止空字符,无论void simple(char *bar) {
char MyArray[12];
strncpy(MyArray, bar, sizeof(MyArray)-1);
MyArray[sizeof(MyArray)-1]= '\0';
}
是否能够这样做。
答案 4 :(得分:0)
char
数组与字符串相似,但不一样。
在C中,
string 是由第一个空字符终止并包含第一个空字符的连续字符序列。 C11dr§7.1.11
void simple (char *bar) {
char MyArray[12];
strcpy(MyArray, bar);
}
我的导师说
MyArray
最多可以复制12个元素,
这是正确的:MyArray[]
最多可以接收12个字符。
strcpy()
将内存从bar
复制到数组MyArray[]
并继续,直到它复制空字符。如果尝试复制多于12个字符(12个字符包括空字符),则结果为未定义行为(UB)。
MyArray
只能存储11个字符
不完全。 MyArray[]
可以存储12个字符。要将该数据视为字符串,空字符必须是其中之一12.当解释为字符串时,该字符串包含所有字符最多为空字符。它还包括 null chracter 。 MyArray[]
的每个元素都可以是'x'
,但是该内存不会是字符串,因为它缺少空字符。
因此,如果接收到的
bar
值为12或更大,则会发生缓冲区溢出。
不完全。如果strcpy()
尝试在MyArray[]
之外写入,则结果未定义。可能发生缓冲区溢出。程序可能会停止等。结果未定义。它是未定义的行为。
我的导师说,只有当
bar
的收到价值为13或更高时,才会发生这种情况。
bar
是一个指针 - 它可能没有“值13”。 bar
可能指向字符串的内存。 字符串包含其终止空字符,因此字符串可以包含12个非空字符和最终空字符,总共13个字符。 MyArray[]
不足以存储该字符串的副本。
谁是对的?
我怀疑脱离是“bar
是13”的不精确含义。我看到教练报告的不正确。