这是一个基本示例:
#include <all the basic stuff>
int main(void) {
char *name = (char *) malloc(2 * sizeof(char));
if(name == NULL) {
fprintf(stderr, "Error: Unable to allocate enough memory!\n");
return EXIT_FAILURE;
}
strcpy(name, "Bob Smith");
printf("Name: %s\n", name);
free(name);
return EXIT_SUCCESS;
}
因为我只分配2个字节的信息(2个字符),所以执行strcpy时应该出现某种错误,对吗?不会发生这种情况,相反,它只是将字符串复制,打印出来,释放内存并成功退出。为什么会发生这种情况,如何正确使用malloc?
您的程序调用未定义的行为。
未定义行为是超出语言规范的行为。根据定义,这意味着您不能保证会得到任何明确定义的行为(例如错误)。该程序明显无效。
使用时strcpy
,该函数仅假定传递给它的缓冲区足够大,可以容纳要复制的字符串。如果假设是错误的,它将尝试在缓冲区之外的区域中写入数据。如果发生这种情况,程序将陷入J.2未定义行为的C规范这种情况:
在以下情况下,该行为是未定义的:
- 将指针加或减到数组对象中或数组对象之外,以及整数类型所产生的结果不会指向或指向同一数组对象。
因此,要strcpy
正确使用,必须手动确保上述关于字符串长度和缓冲区长度的假设成立。为此,一种简单的方法是将缓冲区的长度保存在某个位置,计算要复制的字符串的长度,然后进行比较。
例如:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
size_t bufferSize = 2 * sizeof(char);
char *name = malloc(bufferSize);
if(name == NULL) {
fprintf(stderr, "Error: Unable to allocate enough memory!\n");
return EXIT_FAILURE;
}
size_t length = strlen("Bob Smith");
if(length + 1 > bufferSize) {
fprintf(stderr, "Error: The target buffer is too small!\n");
return EXIT_FAILURE;
}
strcpy(name, "Bob Smith");
printf("Name: %s\n", name);
free(name);
return EXIT_SUCCESS;
}
与此无关的是,您会注意到我没有malloc
void*
转换结果,因为a可以隐式转换为char*
。
最后一点:
当您尝试确保代码的正确性时(因为您正在学习该语言或因为您打算发布该软件),C的这一方面听起来可能不切实际。
这就是为什么有一些工具可以在程序执行无效操作时为您提供错误信息。Valgrind就是这样一种工具(正如乔纳森·莱夫勒(Jonathan Leffler)在评论中提到的那样)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句