c-使用malloc时的奇怪行为



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

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

void myfunction(char* src) {
printf("src: |%s|n", src);
int srcLength = strlen(src);
printf("src length: %dn", 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,我就有了这种尴尬的行为。就好像字符中没有字符一样*:

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

并且我用分配的input调用readStdin

char* input = malloc(400);

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

使用malloc 时的奇怪行为

是的,这很奇怪。。。。或者也许不是。你的代码有未定义的行为,所以一切都可能发生。

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

一旦你有了未定义的行为,就没有理由对正在发生的事情进行推理……但如果我们无论如何都试图这样做,对大多数系统的一个可能解释是:

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

但请注意,以上解释是系统特定的。它不是C标准规定的。尽管如此,大多数系统都是这样工作的。

该怎么办?

代替

char buffer[400];

进行

char* buffer = malloc(400);

正如许多人在评论中所说,您存在范围问题。为了避免这种情况,您需要在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] = '';
}
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将按预期工作。

我不明白为什么在执行char* output = malloc(200);时不会出现编译错误:必须转换为char*,就像char* output = (char*) malloc(200);一样

相关内容

  • 没有找到相关文章