C:malloc()是否忽略请求的大小?

C:malloc()是否忽略请求的大小?,c,malloc,free,C,Malloc,Free,我已经很长时间没有使用C了,显然我忘记的比我想象的要多。在尝试使用malloc()分配字符串时,我不断获取该字符串的旧数据,包括当请求的空间较短时它的旧的、较长的长度。这种情况确实包括指向字符串free()d并设置为NULL的指针。以下是我在终端中看到的示例运行: yes, quit, or other (<-message from program) oooo (<-user input; this will

我已经很长时间没有使用C了,显然我忘记的比我想象的要多。在尝试使用malloc()分配字符串时,我不断获取该字符串的旧数据,包括当请求的空间较短时它的旧的、较长的长度。这种情况确实包括指向字符串free()d并设置为NULL的指针。以下是我在终端中看到的示例运行:

yes, quit, or other            (<-message from program)
oooo                           (<-user input; this will be put to upper case and token'd)

------uIT LENGTH:4             (<-debug message showing length of userInputToken)

preC--tmp:                     (<-contents of tmp variable)

pstC--tmp:OOOO                 (<-contents of temp variable)
bad input                      (<-program response)
yes, quit, or other
yes

------uIT LENGTH:3

preC--tmp:OOOO                 (<-: tmp = malloc(sizeof(char)*(strlen(userInputToken)-1)); )

pstC--tmp:YESO                 (<-: strncpy(tmp,userInputToken,strlen(userInputToken)-1);  )
bad input
yes, quit, or other
yes

------uIT LENGTH:3

preC--tmp:YESO

pstC--tmp:YESO
bad input
yes, quit, or other
quit

------uIT LENGTH:4

preC--tmp:YESO

pstC--tmp:QUIT                 (<-: Successful quit because I only did 4 chars; if 5 were used, this would have failed)
在MessageParserPieces.h中:

outputFlagContainer *getUserInput(outputFlagContainer *outputFlags) {
    outputFlags = resetOutputFlags(outputFlags);
    char *userInput = NULL;
    char user_input[MAX_INPUT];
    char *userInputToken = NULL;
    char *tmp = NULL;
    char *finalCharacterCheck = NULL;

    // Tokens to search for:
    char QUIT[] = "QUIT";
    char YES[] = "YES";

    userInput = fgets(user_input, MAX_INPUT-1, stdin);
    int i = 0;
    while(userInput[i]) {
        userInput[i] = toupper(userInput[i]);
        i++;
    }

    userInputToken = strtok(userInput, " ");
    if (userInputToken) {
        finalCharacterCheck = strchr(userInputToken, '\n');
        if (finalCharacterCheck) {
            int MEOW = strlen(userInputToken)-1; // DEBUG LINE
            printf("\n------uIT LENGTH:%d\n", MEOW); // DEBUG LINE

            // The problem appears to happen here and under the circumstances that
            // userInput is (for example) 4 characters and then after getUserInput()
            // is called again, userInput is 3 characters long. 
            tmp = malloc(sizeof(char)*(strlen(userInputToken)-1));
            if (tmp == NULL) {
                exit(1);
            }

            printf("\npreC--tmp:%s\n", tmp); // This shows that the malloc DOES NOT use the given length.

            strncpy(tmp,userInputToken,strlen(userInputToken)-1);

            printf("\npstC--tmp:%s\n", tmp); // Copies in the correct number of characters.

            userInputToken = tmp;
            free(tmp);
            tmp = NULL;
        }
    }

    while (userInputToken != NULL) { // NULL = NO (more) tokens.
        if (0 == strcmp(userInputToken, YES)) {
            outputFlags->YES = true;
        } else if (0 == strcmp(userInputToken, QUIT)) {
            outputFlags->QUIT = true;
        }

        userInputToken = strtok(NULL, " ");
        if (userInputToken) {
            finalCharacterCheck = strchr(userInputToken, '\n');
            if (finalCharacterCheck) {
                tmp = malloc(sizeof(char)*(strlen(userInputToken)-1));
                if (tmp == NULL) {
                    exit(1);
                }
                strncpy(tmp,userInputToken,strlen(userInputToken)-1);
                userInputToken = tmp;
                free(tmp);
                tmp = NULL;
            }
        }
    }
    return outputFlags;
}
我假设这是某种明显的错误,但今晚我在谷歌上搜索了大约两个小时。我想不出如何搜索这个不带malloc()教程的文档,我已经看过了一些


如果您有任何见解,我们将不胜感激

您可能应该使用calloc。您也不应该像这样使用未初始化的内存。Malloc以块的形式分配内存。当您释放一个块时,它可能会被重用。您无法获得确切的大小,除非使用malloc重置内存,否则无法保证其字节的值。您所知道的是,您有一块至少与您请求的大小一样大的内存可供使用。因此,在本例中,您在写入内存块之前打印内存块的旧内容

您可能应该使用calloc。您也不应该像这样使用未初始化的内存。Malloc以块的形式分配内存。当您释放一个块时,它可能会被重用。您无法获得确切的大小,除非使用malloc重置内存,否则无法保证其字节的值。您所知道的是,您有一块至少与您请求的大小一样大的内存可供使用。因此,在本例中,您在写入内存块之前打印内存块的旧内容

tmp = malloc(sizeof(char)*(strlen(userInputToken)-1));
if (tmp == NULL) {
    exit(1);
}

printf("\npreC--tmp:%s\n", tmp); // This shows that the malloc DOES NOT use the given length.

strncpy(tmp,userInputToken,strlen(userInputToken)-1);
printf("\npstC--tmp:%s\n", tmp); // Copies in the correct number of characters.
这段代码表明您希望
tmp
被初始化。事实并非如此。分配内存后,必须初始化内存。这就是你用strncpy所做的

还有一个问题,因为您没有分配足够的字节来保存字符串,因此无法使用普通的
%s
格式说明符来显示它。您正在分配
strlen(userInputToken)-1
字节并复制相同的数字。这意味着没有空字符的空间,
strncpy
将不会终止字符串。您应该始终再添加一个字节,如果空字符不会被
strncpy
复制,则必须自己设置:

size_t length = strlen(userInputToken)-1;
tmp = malloc(length + 1);
strncpy(tmp, userInputToken, length);
tmp[length] = 0;
所以,我想说清楚,你有三个问题:

  • 在初始化之前显示新分配的“字符串”
  • 您没有分配足够的内存来保存字符串
  • 您不终止字符串(也不终止strncpy,因为它在允许的字节数内没有遇到字符串终止符)

  • 我刚刚在您的
    循环中发现了其他东西(userInputToken!=NULL)
    循环。。。您总是在循环开始时使用
    userInputToken
    进行字符串比较,但在循环内部(以及循环上方的部分),您可以执行以下操作:

    userInputToken = tmp;
    free(tmp);
    
    这意味着
    userInputToken
    是一个悬空指针。它指向已释放的内存,您不能使用它。你必须重新思考你的方法,让它继续存在,直到不再需要它

    这段代码表明您希望
    tmp
    被初始化。事实并非如此。分配内存后,必须初始化内存。这就是你用strncpy所做的

    还有一个问题,因为您没有分配足够的字节来保存字符串,因此无法使用普通的
    %s
    格式说明符来显示它。您正在分配
    strlen(userInputToken)-1
    字节并复制相同的数字。这意味着没有空字符的空间,
    strncpy
    将不会终止字符串。您应该始终再添加一个字节,如果空字符不会被
    strncpy
    复制,则必须自己设置:

    size_t length = strlen(userInputToken)-1;
    tmp = malloc(length + 1);
    strncpy(tmp, userInputToken, length);
    tmp[length] = 0;
    
    所以,我想说清楚,你有三个问题:

  • 在初始化之前显示新分配的“字符串”
  • 您没有分配足够的内存来保存字符串
  • 您不终止字符串(也不终止strncpy,因为它在允许的字节数内没有遇到字符串终止符)

  • 我刚刚在您的
    循环中发现了其他东西(userInputToken!=NULL)
    循环。。。您总是在循环开始时使用
    userInputToken
    进行字符串比较,但在循环内部(以及循环上方的部分),您可以执行以下操作:

    userInputToken = tmp;
    free(tmp);
    

    这意味着
    userInputToken
    是一个悬空指针。它指向已释放的内存,您不能使用它。您必须重新考虑您的方法,并允许其继续使用,直到不再需要为止。

    您用这一行验证分配的长度是不正确的:

    printf("\npreC--tmp:%s\n", tmp); // This shows that the malloc DOES NOT use the given length.
    

    malloc
    将分配请求的字节数,但不会初始化分配的内存。因此,当您尝试将其打印为字符串(应以
    '\0'
    结尾)时,它将尝试打印所有字符,直到在内存中找到
    '\0'
    。终止字符不能来自同一内存块。
    '\0'
    的存在是不确定的。

    您用此行验证分配的长度是不正确的:

    printf("\npreC--tmp:%s\n", tmp); // This shows that the malloc DOES NOT use the given length.
    
    malloc
    将分配请求的字节数,但不会初始化分配的内存。因此,当您尝试将其打印为字符串(应以
    '\0'
    结尾)时,它将尝试打印所有字符,直到在内存中找到
    '\0'
    。终止字符不能来自同一内存块。
    '\0'
    的存在是不确定的。

    我希望这有帮助

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    #define MAX_INPUT 128
    #define true 1
    #define false 0
    
    typedef struct _outputFlagContainer{
    
    int  YES, QUIT;
    
    }outputFlagContainer;
    
    
    void run();
    outputFlagContainer *getUserInput(outputFlagContainer *outputFlags);
    outputFlagContainer *resetOutputFlags(outputFlagContainer *outputFlags);
    
    int main(int argc, char *argv[]){
    
    run();      
    return 0;
    }    
    
    void run() {
    
        outputFlagContainer *outputFlags = malloc(sizeof(outputFlagContainer));
    
        while(true) {       
    
            puts("yes, quit, or other");
    
            outputFlags = getUserInput(outputFlags);
    
            if (outputFlags->YES) 
            {
                puts("It was a yes!");
            }
            else if (outputFlags->QUIT) 
            {
                break;
            }
            else
            {
                puts("bad input");
            }
    
        }
    
        free(outputFlags);
    }
    
    outputFlagContainer *resetOutputFlags(outputFlagContainer *outputFlags) {
    
        if(outputFlags!= NULL){
    
            outputFlags->YES = false;
            outputFlags->QUIT = false;      
    
        }
    
        return outputFlags;
    
    }
    
    outputFlagContainer *getUserInput(outputFlagContainer *outputFlags) {
    
        int len;
        char user_input[MAX_INPUT]={0};     // Zero Initialization
    
        char *userInput = NULL;
        char *userInputToken = NULL;
        char *tmp = NULL;
        char *finalCharacterCheck = NULL;
    
        // Tokens to search for:        // Immutable Strings
        char *QUIT = "QUIT";
        char *YES = "YES";
    
        // Reset The Structure
        outputFlags = resetOutputFlags(outputFlags);
    
        userInput = fgets(user_input, MAX_INPUT, stdin);        // it copies one less than MAX_INPUT 
    
        // Converting to Upper Case
        int i = 0;
        while(userInput[i]) {
            userInput[i] = toupper(userInput[i]);
            i++;
        }
    
        userInputToken = strtok(userInput, " ");
    
        if (userInputToken) {
    
            finalCharacterCheck = strchr(userInputToken, '\n');
    
            if (finalCharacterCheck) {
    
                len = strlen(userInputToken);
    
                printf("\n------uIT LENGTH:%d\n", len); // DEBUG LINE
    
                tmp = malloc(sizeof(char)*(len+1));
                if (tmp == NULL)
                    exit(1);
    
                strncpy(tmp,userInputToken,len);
                tmp[len]='\0';
    
                printf("\npstC--tmp:%s\n", tmp); // Copies in the correct number of characters.
    
                strcpy(user_input,tmp);
                userInputToken = user_input;
                free(tmp);
                tmp = NULL;
            }
        }
    
        while (userInputToken != NULL) { // NULL = NO (more) tokens.
    
            if (0 == strcmp(userInputToken, YES)) {
    
                outputFlags->YES = true;
    
            } 
            else if (0 == strcmp(userInputToken, QUIT)) {
    
                outputFlags->QUIT = true;
    
            }
    
            userInputToken = strtok(NULL, " ");
    
            if (userInputToken) {
    
                finalCharacterCheck = strchr(userInputToken, '\n');
    
                if (finalCharacterCheck) {
    
                    len = strlen(userInputToken);        
                    tmp = malloc(sizeof(char)*(len+1));
                    if (tmp == NULL) {
                        exit(1);
                    }
    
                    strncpy(tmp,userInputToken,len);
                    tmp[len]='\0';
    
                    strcpy(user_input,tmp);
                    userInputToken = user_input;                                                
                    free(tmp);
                    tmp = NULL;
                }
            }
        }
    
        return outputFlags;
    }
    
    #包括
    #包括
    #在