C++ memcpy(),未初始化的局部变量
最初,我在ubuntu上运行了这段代码,它运行得很好,没有任何警告。但是,当我在windows上的VS上运行它时,它表示“操作数1未初始化”。我想知道怎么会出问题 我知道不投malloc的结果,但VS只是不断发出警告 程序应该采用9字节的字符数组。第一个字节表示算术运算,其他8个字节表示2个整数,每个4位数字4个字节。 代码如下:C++ memcpy(),未初始化的局部变量,c++,memcpy,C++,Memcpy,最初,我在ubuntu上运行了这段代码,它运行得很好,没有任何警告。但是,当我在windows上的VS上运行它时,它表示“操作数1未初始化”。我想知道怎么会出问题 我知道不投malloc的结果,但VS只是不断发出警告 程序应该采用9字节的字符数组。第一个字节表示算术运算,其他8个字节表示2个整数,每个4位数字4个字节。 代码如下: #include <stdio.h> #include <string.h> #include <stdlib.h> float
#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;
}
我真的不知道你期望会发生什么,但这是完全错误的
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));
为什么是sizeofint?缓冲区大概是一个指向字符数组的指针,并且没有特别的理由选择sizeofint,因为结果只是传递到atoi中。atoi函数只取一个指向以NUL结尾的字符数组的指针,sizeofint只是atoi结果的大小,而不是输入的大小
如何让它工作
以下是如何在不调用未定义行为的情况下执行此操作:
char tmp[5];
memcpy(tmp, buffer, 4); // don't use sizeof(int), just use 4
tmp[4] = '\0'; // add NUL terminator
int op0 = atoi(tmp);
memcpy(tmp, buffer + 5, 4);
// NUL terminator already present in tmp
int op1 = atoi(tmp);
请注意,当您将tmp传递给memcpy时,它将转换为char*类型的指针,该指针指向tmp的第一个元素。有点像做以下事情:
char tmp[5];
char *my_ptr = &tmp[0];
memcpy(my_ptr, ...);
您可以看到这与:
char *my_ptr; // uninitialized
memcpy(my_ptr, ...);
当我在windows上的VS上运行它时,它表示_operan1未初始化。我想知道怎么会出问题
使用未初始化的值会导致未定义的行为,这意味着允许发生任何事情。这就是它可能出错的原因
我知道不投malloc的结果,但VS只是不断发出警告
<>你是否将你的代码编译成C++?因为C++不允许从空隙*中隐式转换,而C确实如此。难道不应该复制缓冲区中的内容吗?缓冲区是函数参数。我的意思是它可以在ubuntu上运行,而且它完全符合我的要求,但不能在windows上运行。这就是我来这里的原因。@sstefan:我可以向你保证Ubuntu上的错误。不管您使用的是什么系统,这都是100%错误的。@sstefan:请记住,函数不能初始化其参数。相反,memcpy将初始化其参数所指向的内容,但一般来说,函数不可能初始化其参数。如果您愿意,我可以发布屏幕截图。多次尝试times@sstefan:请不要发布屏幕截图。即使你的程序给出了正确的答案,它仍然是一个错误的程序。你也可以尝试使用Valgrind或Ubuntu编译上的地址消毒器运行该程序,并使用-fsanize=address链接。这将证明程序在Ubuntu上也是错误的,而不仅仅是Windows。如果你得到一个关于不空出的警告/错误,你就不用C编译器,但很可能是C++编译器。因此,这是C++,而不是C,仅仅用一个下划线来区分两个变量是非常糟糕的练习。别这样!警告非常明确。你认为memcpy在哪里复制数据?