我是 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;
}
myfunction
和readStdin
位于不同的文件中,但我希望无所谓。
更新2:
根据评论中的支持者的提议,我做了范围问题的决议。
我将readStdin
的函数原型更改为:
char* readStdin(char* input);
我使用分配的readStdin
调用input
。
char* input = malloc(400);
在readStdin
中,我使用函数参数替换了buffer
。
答案 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);