memcpy(),未初始化的局部变量

时间:2017-03-10 19:49:11

标签: c++ memcpy

最初,我在ubuntu上运行了这个代码,它运行得很好,没有任何警告。但是,当我在Windows上的VS上运行时,它表示_operand1未初始化。我想知道它怎么会出问题。

我知道没有投射malloc的结果,但VS只是不停地发出警告。

程序应该采用9个字节的char数组。第一个字节表示算术运算,另外8个表示每个4个字节的2个整数(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;

}

2 个答案:

答案 0 :(得分:3)

我真的不知道你期望发生什么,但这是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),因为结果只是传递给atoiatoi函数只接受一个指向NUL终止字符数组的指针,sizeof(int)只是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, ...);

您可以看到这与以下内容有何不同:

+-----------+--------------+--------------------+
|   Date    |   Returns    | Final Return Index |
+-----------+--------------+--------------------+
| 11/1/2016 |  0.000542159 |        1.000542159 |
| 11/2/2016 | -0.001629094 |        0.998912181 |
| 11/3/2016 |  0.000568779 |        0.999480341 |
| 11/4/2016 | -0.001246407 |        0.998234581 |
| 11/7/2016 |  0.000795611 |        0.999028788 |
| 11/8/2016 |  0.000663507 |        0.999691651 |
| 11/9/2016 | -0.000254819 |         0.99943691 |
+-----------+--------------+--------------------+

答案 1 :(得分:1)

  

当我在Windows上的VS上运行时,它表示_operand1未初始化。我想知道它怎么会出问题。

使用未初始化的值会导致未定义的行为,这意味着允许任何事情发生。这就是它出错的方式。

  

我知道没有投射malloc的结果,但VS只是不停地发出警告。

您是否有机会将代码编译为C ++?因为C ++不允许来自void*的隐式转换,而C允许隐式转换。