使用malloc时的奇怪行为

时间:2017-10-29 17:42:16

标签: c malloc stdin

我是 C 的新手,在使用malloc时遇到奇怪的行为。

我从stdin(fgets)读取输入文本并将其传递给函数myfunction。

void myfunction(char* src) {

     printf("src: |%s|\n", src);

     int srcLength = strlen(src);
     printf("src length: %d\n", srcLength);

     // CAUSES ODD BEHAVIOR IN MY SITUATION
     // char* output = malloc(200);
     //
     // if (output == NULL) {
     //   exit(EXIT_FAILURE);
     // }

     for (int i=0; i < srcLength; ++i) {
       char currChar = src[i];
       printf("|%c| ", currChar);
     }
}

当执行没有malloc的函数时(参见注释),我得到了这个:

src: |asdf|
src length: 4
|a| |s| |d| |f|

但是对于malloc,我会遇到这种尴尬的行为。好像char *中没有字符:

src: |asdf|
src length: 4
|| || || || 

char * src可能存在问题(来自stdin)。但我不确定,因为输入字符串打印正确(src: |asdf|)。

任何人都可以支持我,如何分析问题的根源?

更新1:

这是从stdin读取并调用myfunction的代码。

int main(int argc, char **argv) {

  char *input = NULL;
  input = readStdin();
  myfunction(input);
  return EXIT_SUCCESS;
}

char* readStdin(void) {
    char buffer[400];
    char *text = fgets(buffer, sizeof(buffer), stdin);
    return text;
}

myfunctionreadStdin位于不同的文件中,但我希望无所谓。

更新2:

根据评论中的支持者的提议,我做了范围问题的决议。

我将readStdin的函数原型更改为:

 char* readStdin(char* input);

我使用分配的readStdin调用input

 char* input = malloc(400);

readStdin中,我使用函数参数替换了buffer

3 个答案:

答案 0 :(得分:1)

  

使用malloc时的奇怪行为

是的,它很奇怪......或许不是。您的代码具有未定义的行为,因此一切都可能发生。

问题是如果text成功,buffer最终将成为指向fgets的指针。但buffer是函数中的局部变量,因此只要readStdin返回变量buffer,就不再存在。因此,您传递myfunction无效指针,当您使用它时(即读/写),您有未定义的行为。

一旦你有未定义的行为,理由发生了什么是没有意义的......但如果我们试图这样做,大多数系统的可能解释是:

buffer位于堆栈上。当readStdin返回时,堆栈指针递减(或递增),以便buffer现在位于堆栈的未使用部分。当你调用一个新函数时,新函数也需要一些堆栈空间。多少取决于函数使用的变量数量。换句话说 - 变量越多,所需的堆栈空间就越多。由于新变量将覆盖堆栈的某些部分 - 从而覆盖包含过时buffer变量的内存部分 - buffer的破坏量可能会随着函数调用中的变量数量而变化。这可能就是你所看到的。

但请注意,上述说明是系统特定的。它不是C标准规定的东西。不过,这就是大多数系统的工作方式。

怎么办?

而不是

char buffer[400];

DO

char* buffer = malloc(400);

答案 1 :(得分:0)

正如许多人在评论中所述,你有范围问题。为避免这种情况,您需要在readStdin()内分配内存。从评论中引用@MOehm

  

一旦你离开了readStdin,缓冲区就变得无效了。访问它是未定义的行为,您应该避免。 (我猜这个问题不是malloc,而是附加的变量输出,它碰巧占用了以前被缓冲区占用的部分空间,从而破坏了它。)

#define SIZE 400

char* readStdin(void) {
    char buffer[SIZE];
    char *text = NULL

    fgets(buffer, sizeof(buffer), stdin);
    text = malloc(sizeof(char) * (strlen(buffer) + 1));//allocate memory
    strcpy(text, buffer);//and copy the buffer into it.

    int length = strlen(text);
    if (text[length - 1] == '\n') {
        text[length - 1] = '\0';
    }
    return text;
}

现在你的主要功能应该是这样的:

int main(int argc, char *argv[]) 
{
    char *input = NULL;
    input = readStdin();
    myfunction(input);
    free(input);//must now free it.
    input = NULL;
    return EXIT_SUCCESS;
}

尝试进行这些更改,您会发现所有问题都将消失。现在MyFunction将按预期工作。

答案 2 :(得分:-1)

我不明白为什么在执行char* output = malloc(200);时你不会遇到编译错误:你必须加入char*,如char* output = (char*) malloc(200);