0

I've been learning C for a few weeks. I have solved my problem by using malloc() to allocate some memory on the heap. I have an inkling about why my code failed but I'm not 100% sure. Unfortunately I am self-teaching so I have to turn to you kind people on the internet.

Code description Calls a function getString() which declares an array, fills the array using the inbuilt getchar() and returns a pointer to that array.

The issue I print the returned pointer value and everything is fine. BUT when I pass it to another function that simply spits it back out and try to print that, the end of the string is cut off, sometimes it spits out a nonsense character.

What I think could be happening The original array is only in use for as long as the getString() function & so C is using some of the memory in the array address to store other things.

Is my intuition correct? If not, could someone point me in the right direction?

#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;
}

Here is my amended getString() which behaves correctly.

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

Update: Thanks for all the answers! Very much appreciated.

danielgormly
  • 1,050
  • 1
  • 7
  • 16
  • 1
    Yeah, you have undefined behaviour because you're using the address of a variable on the stack _outside_ of the stack context in which it was valid. I was pleased to see you mention `malloc` in your question, but I don't see it used anywhere in code. – paddy Mar 28 '17 at 07:57
  • Thank you! Sorry I'm posting the broken code because I wanted to confirm that was the case! I'll update my answer with my fix too. – danielgormly Mar 28 '17 at 08:25

2 Answers2

1

getString returns the address of function local variable with automatic storage duration, the address of arr. Any attempt to access arr via that address after the function returns has undefined behavior.

There is no guarantee by the C standard it will preserve its value. There is no guarantee it won't. There is no obligation by the compiler to even produce a valid program when you break a language constraint like that.

6.2.4 Storage durations of objects ¶2

The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

The lifetime mentioned above is from the opening brace up to the closing brace of getString, for as long as its executing only. No more, no less.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
1

char *string = arr; is wrong because you did not allocate memory for arr; it is a variable on the stack. Upon return, the stack memory is relerased and so you return a pointer to a released variable.

Use malloc instead, e.g.:

string= malloc(strlen(arr)+1);
strcpy(string,arr);
return string;
Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41