【问题标题】:Char array corrupted after its pointer is passed between functions [duplicate]Char 数组在其指针在函数之间传递后损坏 [重复]
【发布时间】:2017-03-28 07:54:09
【问题描述】:

我已经学习 C 几个星期了。我通过使用malloc() 在堆上分配一些内存解决了我的问题。我对我的代码失败的原因有所了解,但我不能 100% 确定。不幸的是,我是自学的,所以我不得不求助于互联网上的好心人。

代码说明调用声明数组的函数getString(),使用内置的getchar() 填充数组并返回指向该数组的指针。

问题我打印了返回的指针值,一切都很好。但是当我将它传递给另一个简单地将其吐出并尝试打印它的函数时,字符串的结尾被切断,有时它会吐出一个无意义的字符。

我认为可能发生的事情 原始数组仅在 getString() 函数中使用,因此 C 正在使用数组地址中的一些内存来存储其他内容。

我的直觉正确吗?如果没有,有人可以指出我正确的方向吗?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLEN 100

char * getString(void);
char * doSomethingWith(char *);

int main(void)
{
    char *string1 = getString();
    printf("String: %s\n", string1);
    char *string2 = doSomethingWith(string1);
    printf("String: %s\n", string2); // This print out is unreliable!
    return EXIT_SUCCESS;
}

char * getString(void) {
    int c;
    char arr[MAXLEN];
    char *string = arr;
    char *cur = arr;

    while((c = getchar()) != '\n' && c != EOF) {
        if(cur - string < MAXLEN - 2) {
            *cur++ = c;
        }
    }
    *cur = '\0'; // Terminate string

    return string;
}

char * doSomethingWith(char *string) {
    return string;
}

这是我修改后的 getString() 行为正确。

char * getString(void) {
    int c;
    char *string = malloc(sizeof *string * MAXLEN);
    char *cur = string;

    while((c = getchar()) != '\n' && c != EOF) {
        if(cur - string < MAXLEN - 2) {
            *cur++ = c;
        }
    }
    *cur = '\0'; // Terminate string

    return string;
}

更新:感谢所有回答!非常感谢。

【问题讨论】:

  • 是的,您有未定义的行为,因为您使用的是堆栈上下文中有效的堆栈外部上的变量地址。我很高兴看到您在问题中提到 malloc,但我没有看到它在代码中的任何地方使用。
  • 谢谢!抱歉,我发布了损坏的代码,因为我想确认是这种情况!我也会用我的修复来更新我的答案。

标签: c pointers


【解决方案1】:

char *string = arr; 是错误的,因为您没有arr 分配内存;它是堆栈上的变量。返回时,堆栈内存被释放,因此您返回一个指向已释放变量的指针。

请改用malloc,例如:

string= malloc(strlen(arr)+1);
strcpy(string,arr);
return string;

【讨论】:

  • 非常感谢。这就是我认为正在发生的事情!
【解决方案2】:

getString返回自动存储时长的函数局部变量的地址,arr的地址。函数返回后通过该地址访问arr 的任何尝试都有未定义的行为。

C 标准不保证它会保持其价值。不能保证它不会。当你打破这样的语言约束时,编译器甚至没有义务生成一个有效的程序。

6.2.4 Storage durations of objects ¶2

对象的生命周期是程序执行期间保证为其保留存储的部分。一个对象存在,具有一个常量地址,33) 并在其生命周期内保留其最后存储的值。34) 如果一个对象在其生命周期之外被引用,则行为是未定义的。当指针指向(或刚刚过去)的对象到达其生命周期结束时,指针的值变得不确定。

上面提到的生命周期是从 getString 的左大括号到右大括号,只要它执行。不多也不少。

【讨论】:

  • 谢谢!这是我理解的事情,但我不知道如何确认
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-29
  • 2016-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多