繁体   English   中英

为什么这些相似的函数不会引发相同的错误?

[英]Why don't this similar functions throw the same error?

我有两个具有相同返回类型的函数:

char * getRandomWord(char wordlist[WORDLIST_LENGTH][WORD_LENGTH]) {
    int random = rand() % WORDLIST_LENGTH;
    return wordlist[random];
}

char * revealInString(char * s, int * r) {
    size_t strLength = strlen(s);
    char revealedString[strLength + 1];
    for (int i = 0; i < strLength; i++) {
        revealedString[i] = '_';
    }
    for (int i = 0; i < strLength; i++) {
        if (r[i] != NULL) {
            int positionToReveal = r[i];
            revealedString[positionToReveal] = s[positionToReveal];
        }
    }
    revealedString[strLength - 1] = '\0';
    return revealedString;
}

第一个工作正常,而我的IDE(CLion)在第二个工作中显示了一个问题: Value escapes the local scope

为什么第二个函数显示该错误,而第一个函数也返回没有问题的字符数组?

语法char revealedString[N]定义了在堆栈上分配的VLA(C99功能)。

...但是您的revealInString函数然后返回一个指向堆栈分配的内存的指针。 这是一个错误:当您的函数返回时,将弹出堆栈,因此revealedString现在指向无效的内存。

相比之下,您的第一个示例将返回指向在调用函数之前分配的内存的指针。

尽管在堆栈上分配然后返回的函数可以工作(前提是调用者不做进一步的调用),但这是一个非常糟糕的主意,因为它取决于未定义的行为。

您可以通过以下两种方法解决此问题:

  1. 在调用revealInString之前,让调用方在堆栈上分配VLA
  2. 在堆上分配数组(用callocmalloc ),并确保调用者完成调用后可以free它们。

范例1:

char revealedStringBuffer[ strlen(s) + 1 ];
revealInString( revealedStringBuffer, r ); // and change `revealInString` to return void

范例2:

char * revealInString(char * s, int * r) {
    size_t strLength = strlen(s);
    char* revealedString = calloc( strLength + 1, sizeof(char) );
    if( revealedString == NULL ) die("calloc failure.");

    for (int i = 0; i < strLength; i++) {
        revealedString[i] = '_';
    }
    for (int i = 0; i < strLength; i++) {
        if (r[i] != NULL) {
            int positionToReveal = r[i];
            revealedString[positionToReveal] = s[positionToReveal];
        }
    }
    revealedString[strLength - 1] = '\0';
    return revealedString;
}

// Usage:
char* revealedString = revealInString( s, r );
free( revealedString );

它们都不返回数组。 他们返回一个指针(指向char )。

在第二个函数中,返回的指针指向局部变量。 函数返回时,局部变量将被销毁,因此返回的指针无效。 这就是为什么编译器会警告您的原因。

在第一种情况下,您将返回调用方传递的指针,因此如果该指针有效,则在函数返回时它将仍然有效。

暂无
暂无

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

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