C语言面试高频题——strcat、strncat、strcmp、strcpy 哪些函数会导致内存溢出?
1. 函数功能与内存溢出风险
(1) strcat
-
功能:将源字符串追加到目标字符串的末尾。
-
原型:
char *strcat(char *dest, const char *src);
-
内存溢出风险:
strcat
不会检查目标缓冲区的大小,直接将源字符串追加到目标字符串后。- 如果目标缓冲区不足以容纳追加的结果,会导致内存溢出。
-
示例:
char dest[10] = "Hello"; strcat(dest, " World!"); // 内存溢出:目标缓冲区不足
改进方法:
- 使用更安全的函数
strncat
,并明确指定最大追加长度。strncat(dest, " World!", sizeof(dest) - strlen(dest) - 1);
(2) strncat
-
功能:将源字符串的前
n
个字符追加到目标字符串的末尾。 -
原型:
char *strncat(char *dest, const char *src, size_t n);
-
内存溢出风险:
- 如果
n
的值过大,仍可能导致目标缓冲区溢出。 - 需要确保
n
不超过目标缓冲区剩余空间。
- 如果
-
示例:
char dest[10] = "Hello"; strncat(dest, " World!", 10); // 内存溢出:目标缓冲区不足
改进方法:
- 手动计算目标缓冲区的剩余空间,避免超出范围。
strncat(dest, " World!", sizeof(dest) - strlen(dest) - 1);
(3) strcmp
-
功能:比较两个字符串的字典顺序。
-
原型:
int strcmp(const char *s1, const char *s2);
-
内存溢出风险:
strcmp
本身不会导致内存溢出,因为它只是逐字符比较两个字符串。- 但如果传入的字符串未以
\0
结尾(即非法字符串),可能会引发未定义行为。
-
改进方法:
-
确保输入字符串是合法的以
\0
结尾的字符串。if (strcmp(str1, str2) == 0) {// 字符串相等 }
(4) strcpy
-
功能:将源字符串复制到目标字符串。
-
原型:
char *strcpy(char *dest, const char *src);
-
内存溢出风险:
strcpy
不会检查目标缓冲区的大小,直接将源字符串复制到目标缓冲区。- 如果目标缓冲区不足以容纳源字符串,会导致内存溢出。
-
示例:
char dest[10]; strcpy(dest, "This is a long string"); // 内存溢出:目标缓冲区不足
改进方法:
- 使用更安全的函数
strncpy
,并明确指定最大复制长度。strncpy(dest, "This is a long string", sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0'; // 确保字符串以 \0 结尾
2. 改进总结:如何避免内存溢出?
为了避免上述函数引发的内存溢出问题,可以采取以下措施:
(1) 使用更安全的替代函数
strcat
→strncat
strcpy
→strncpy
(2) 明确指定缓冲区大小
- 在调用
strncat
或strncpy
时,始终明确指定目标缓冲区的大小。 - 示例:
char dest[10]; strncpy(dest, src, sizeof(dest) - 1); dest[sizeof(dest) - 1] = '\0'; // 确保字符串以 \0 结尾
(3) 使用现代安全函数
- 在支持 C11 或更高版本的编译器中,可以使用更安全的函数,如
strlcpy
和strlcat
(需安装扩展库)。 - 示例:
strlcpy(dest, src, sizeof(dest)); // 自动截断并确保以 \0 结尾 strlcat(dest, src, sizeof(dest)); // 自动截断并确保以 \0 结尾
(4) 检查输入数据
- 确保输入字符串是合法的以
\0
结尾的字符串。 - 对用户输入的数据进行验证和限制。
3. 总结对比
函数 | 功能 | 是否可能导致内存溢出 | 改进方法 |
---|---|---|---|
strcat | 追加字符串 | 是 | 使用 strncat 并明确指定最大追加长度 |
strncat | 追加前 n 个字符 | 是(如果 n 过大) | 计算目标缓冲区剩余空间,避免超出范围 |
strcmp | 比较字符串 | 否 | 确保输入字符串以 \0 结尾 |
strcpy | 复制字符串 | 是 | 使用 strncpy 并明确指定最大复制长度 |
4. 结论
- 易导致内存溢出的函数:
strcat
和strcpy
。 - 改进方法:
- 使用
strncat
和strncpy
,并明确指定缓冲区大小。 - 使用现代安全函数(如
strlcpy
和strlcat
)。 - 始终确保目标缓冲区足够大,并手动添加
\0
终止符。
- 使用