I am new to C and facing an odd behavior when using malloc.
I read a input text from stdin (fgets) and pass it to a function 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);
}
}
When executing the function without malloc (see comment), I am getting this:
src: |asdf|
src length: 4
|a| |s| |d| |f|
But with malloc, I am getting this awkward behaviour. As if there were no chars in the char*:
src: |asdf|
src length: 4
|| || || ||
There might be an issue with the char* src (from stdin). But I am unsure because the input string is printed correctly (src: |asdf|
).
Can anybody support me, how to analyze the source of the problem?
UPDATE 1:
Here is the code for reading from stdin and invoking 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;
}
The myfunction
and readStdin
are in different files, but I hope it does not matter.
UPDATE 2:
As proposed by the supporters in the comments, I did a resolution of the scope issue.
I changed the function prototype of readStdin
to:
char* readStdin(char* input);
And I invoke readStdin
with the allocated input
.
char* input = malloc(400);
In readStdin
I replaced buffer
with the function parameter.
Odd behaviour when using malloc
Yes, it's odd.... or perhaps not. You code has undefined behavior so everything may happen.
The problem is that text
will end up as a pointer to buffer
if fgets
is succesful. But buffer
is a local variable in the function so as soon as readStdin
returns the variable buffer
doesn't exist anymore. Therefore you pass myfunction
an invalid pointer and when you use it (i.e. for read/write), you have undefined behavior.
Once you have undefined behavior it makes no sense to reason about what is going on.... but if we try to do that anyway, a likely explanation for most systems is:
buffer
was located on the stack. When readStdin
returns, the stack pointer is decrement (or incremented) so that buffer
is now on the unused part of the stack. When you call a new function, the new function will also need some stack space. How much depends on the number of variables used by the function. In other words - the more variables, the more stack space will be needed. Since the new variables will overwrite some part of the stack - and thereby overwrite parts of the memory holding the obsolete buffer
variable - the amount of destruction of buffer
may change with the number of variables in the function call. That is probably what you see.
But notice that the above explanation is system specific. It is not something specified by the C standard. Still, that is how most systems work.
What to do?
Instead of
char buffer[400];
do
char* buffer = malloc(400);