memcpy(),未初始化的局部变量
memcpy(), uninitialized local variable
最初,我 运行 此代码在 ubuntu 上,它运行良好,没有任何警告。但是,当我 运行 它在 windows 上的 VS 上时,它说 _operand1
未初始化。我想知道它怎么会出错。
我知道不转换 malloc 的结果,但 VS 只是不断抛出警告。
程序应该采用 9 字节的字符数组。第一个字节表示算术运算,其他8个表示2个int,每个4字节(4位数字)。
这是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
float* calculate(char *, int *, int *);
int main() {
char buffer[9];
gets_s(buffer);
int a, b;
float* rez = calculate(buffer, &a, &b);
printf("Operand1: %d, Operand 2: %d\n Result: %f\n", a, b, *rez);
return 0;
}
float* calculate(char *buffer, int *a, int *b) {
char operation;
char *_operand1;
char *_operand2;
int operand1, operand2;
memcpy(_operand1, buffer + 1, sizeof(int));
_operand2 = (buffer + 5);
operand1 = atoi(_operand1);
operand2 = atoi(_operand2);
operation = buffer[0];
float *rez = (float *)malloc(sizeof(float));
switch (operation) {
case '0':
*rez = (float)(operand1 + operand2);
break;
case '1':
*rez = (float)(operand1 - operand2);
break;
case '2':
*rez = (float)(operand1 * operand2);
break;
case '3':
*rez = (float)operand1 / operand2;
break;
}
return rez;
}
我真的不知道你期望发生什么,但这是 100% 错误的。
char *_operand1; /* uninitialized */
char *_operand2; /* uninitialized */
int operand1, operand2;
/* _operand1 is still uninitialized... */
memcpy(_operand1, buffer + 1, sizeof(int));
在这里调用 memcpy()
不会有好事发生。绝对最好的情况是你的程序会崩溃。然而,它可能不会崩溃,这是一件可怕的事情……如果它没有崩溃,它在做什么?它可能正在做您不希望它做的事情。
进一步分析
该代码总体上非常可疑。
memcpy(_operand1, buffer + 1, sizeof(int));
为什么sizeof(int)
? buffer
是一个指向字符数组的指针,据推测,没有特别的理由选择 sizeof(int)
,因为结果只是传递给 atoi
。 atoi
函数只接受一个指向以 NUL 结尾的字符数组的指针,sizeof(int)
只是 atoi
的 result 的大小,而不是 atoi
输入的大小。
如何让它发挥作用
下面是如何在不调用未定义行为的情况下执行此操作:
char tmp[5];
memcpy(tmp, buffer, 4); // don't use sizeof(int), just use 4
tmp[4] = '[=12=]'; // add NUL terminator
int op0 = atoi(tmp);
memcpy(tmp, buffer + 5, 4);
// NUL terminator already present in tmp
int op1 = atoi(tmp);
请注意,当您将 tmp
传递给 memcpy
时,它会转换为指向 tmp
的第一个元素的 char *
类型的指针。有点像做以下事情:
char tmp[5];
char *my_ptr = &tmp[0];
memcpy(my_ptr, ...);
您可以看到这与以下内容有何不同:
char *my_ptr; // uninitialized
memcpy(my_ptr, ...);
when I run it on VS on windows it says _operand1
is not initialized. I'm wondering how it can go wrong.
使用未初始化的值会导致未定义的行为,这意味着允许发生任何事情。这就是它可能出错的原因。
I know about not casting results of malloc, but VS just keeps throwing warnings.
您是否有机会将您的代码编译为 C++?因为 C++ 不允许从 void*
进行隐式转换,而 C 允许
最初,我 运行 此代码在 ubuntu 上,它运行良好,没有任何警告。但是,当我 运行 它在 windows 上的 VS 上时,它说 _operand1
未初始化。我想知道它怎么会出错。
我知道不转换 malloc 的结果,但 VS 只是不断抛出警告。
程序应该采用 9 字节的字符数组。第一个字节表示算术运算,其他8个表示2个int,每个4字节(4位数字)。 这是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
float* calculate(char *, int *, int *);
int main() {
char buffer[9];
gets_s(buffer);
int a, b;
float* rez = calculate(buffer, &a, &b);
printf("Operand1: %d, Operand 2: %d\n Result: %f\n", a, b, *rez);
return 0;
}
float* calculate(char *buffer, int *a, int *b) {
char operation;
char *_operand1;
char *_operand2;
int operand1, operand2;
memcpy(_operand1, buffer + 1, sizeof(int));
_operand2 = (buffer + 5);
operand1 = atoi(_operand1);
operand2 = atoi(_operand2);
operation = buffer[0];
float *rez = (float *)malloc(sizeof(float));
switch (operation) {
case '0':
*rez = (float)(operand1 + operand2);
break;
case '1':
*rez = (float)(operand1 - operand2);
break;
case '2':
*rez = (float)(operand1 * operand2);
break;
case '3':
*rez = (float)operand1 / operand2;
break;
}
return rez;
}
我真的不知道你期望发生什么,但这是 100% 错误的。
char *_operand1; /* uninitialized */
char *_operand2; /* uninitialized */
int operand1, operand2;
/* _operand1 is still uninitialized... */
memcpy(_operand1, buffer + 1, sizeof(int));
在这里调用 memcpy()
不会有好事发生。绝对最好的情况是你的程序会崩溃。然而,它可能不会崩溃,这是一件可怕的事情……如果它没有崩溃,它在做什么?它可能正在做您不希望它做的事情。
进一步分析
该代码总体上非常可疑。
memcpy(_operand1, buffer + 1, sizeof(int));
为什么sizeof(int)
? buffer
是一个指向字符数组的指针,据推测,没有特别的理由选择 sizeof(int)
,因为结果只是传递给 atoi
。 atoi
函数只接受一个指向以 NUL 结尾的字符数组的指针,sizeof(int)
只是 atoi
的 result 的大小,而不是 atoi
输入的大小。
如何让它发挥作用
下面是如何在不调用未定义行为的情况下执行此操作:
char tmp[5];
memcpy(tmp, buffer, 4); // don't use sizeof(int), just use 4
tmp[4] = '[=12=]'; // add NUL terminator
int op0 = atoi(tmp);
memcpy(tmp, buffer + 5, 4);
// NUL terminator already present in tmp
int op1 = atoi(tmp);
请注意,当您将 tmp
传递给 memcpy
时,它会转换为指向 tmp
的第一个元素的 char *
类型的指针。有点像做以下事情:
char tmp[5];
char *my_ptr = &tmp[0];
memcpy(my_ptr, ...);
您可以看到这与以下内容有何不同:
char *my_ptr; // uninitialized
memcpy(my_ptr, ...);
when I run it on VS on windows it says
_operand1
is not initialized. I'm wondering how it can go wrong.
使用未初始化的值会导致未定义的行为,这意味着允许发生任何事情。这就是它可能出错的原因。
I know about not casting results of malloc, but VS just keeps throwing warnings.
您是否有机会将您的代码编译为 C++?因为 C++ 不允许从 void*
进行隐式转换,而 C 允许