简体   繁体   English

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

[英]memcpy(), uninitialized local variable

Initially, i ran this code on ubuntu and it worked just fine without any warnings whatsoever. 最初,我跑在Ubuntu这个代码和它的工作就好了不用任何警告。 However, when I run it on VS on windows it says _operand1 is not initialized. 但是,当我在Windows上的VS上运行它时,它说_operand1未初始化。 I'm wondering how it can go wrong. 我想知道它怎么会出错。

I know about not casting results of malloc, but VS just keeps throwing warnings. 我知道不是强制转换malloc的结果,但是VS只会不断抛出警告。

Program is supposed to take char array of 9 bytes. 程序应该采用9个字节的char数组。 First byte represents arithmetic operation, and other 8 represent 2 ints 4 bytes each (4-digit numbers). 第一字节代表算术运算,及其他8表示2个整数4字节,每字节(4位数字)。 Here is the code: 这是代码:

#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;

}

I really don't know what you expect to happen, but this is 100% wrong. 我真的不知道您会发生什么,但这是100%错误的。

char *_operand1; /* uninitialized */
char *_operand2; /* uninitialized */

int operand1, operand2;

/* _operand1 is still uninitialized... */
memcpy(_operand1, buffer + 1, sizeof(int));

Nothing good can happen when you call memcpy() here. 在这里调用memcpy()不会有任何好处。 The absolute best-case scenario is that your program will crash. 绝对最佳情况是程序将崩溃。 However, it might not crash, and that is an awful thing to ponder… if it's not crashing, what is it doing? 但是,它可能不会崩溃,这是值得思考的可怕事情……如果没有崩溃,它在做什么? It's probably doing something you don't want it to do. 它可能正在做您不希望做的事情。

Further analysis 进一步分析

The code is very suspicious in general. 该代码通常非常可疑。

memcpy(_operand1, buffer + 1, sizeof(int));

Why sizeof(int) ? 为什么选择sizeof(int) buffer is a pointer to an array of characters, presumably, and there's no particular reason to choose sizeof(int) , since the result is just passed into atoi . buffer大概是一个指向字符数组的指针,并且没有特别的理由选择sizeof(int) ,因为结果只是传递给了atoi The atoi function just takes a pointer to an NUL-terminated array of characters, sizeof(int) is just the size of the result of atoi not the size of the input. atoi函数只是使用一个指向以NUL终止的字符数组的指针, sizeof(int)只是atoi 结果的大小而不是输入的大小。

How to make it work 如何运作

Here is how you would do this without invoking undefined behavior: 这是在不调用未定义行为的情况下如何执行此操作:

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);

Note that when you pass tmp to memcpy , it is converted to a pointer of type char * that points to the first element of tmp . 请注意,将tmp传递给memcpy ,它将转换为char *类型的指针,该指针指向tmp的第一个元素。 Kind of like doing the following: 有点像执行以下操作:

char tmp[5];
char *my_ptr = &tmp[0];
memcpy(my_ptr, ...);

You can see how this is different from: 您可以看到这与以下内容有何不同:

char *my_ptr; // uninitialized
memcpy(my_ptr, ...);

when I run it on VS on windows it says _operand1 is not initialized. 当我在Windows上的VS上运行它时,它说_operand1未初始化。 I'm wondering how it can go wrong. 我想知道它怎么会出错。

Using an uninitialized value results in undefined behavior, which means anything is allowed to happen. 使用未初始化的值会导致未定义的行为,这意味着任何事情都可以发生。 That's how it can go wrong. 这样就可能出错。


I know about not casting results of malloc, but VS just keeps throwing warnings. 我知道不是强制转换malloc的结果,但是VS只会不断抛出警告。

Are you by any chance compiling your code as C++? 您是否有机会将代码编译为C ++? Because C++ doesn't allow implicit conversions from void* , whereas C does. 由于C ++不允许从void*进行隐式转换,而C则允许。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM