Token
Token

Reputation: 45

Losing data when passing const char* to function

I've been having a problem with some c code for a few days now, I've looked everywhere but I'm not sure how to fix it and it's driving me crazy! Basically what happens is that function _getfile() gets a relative/absolute filepath from argv[1] (presumed it is available) and checks if an absolute filepath exists and if the file can be opened and read. The function then returns that filepath to main and stores it as a const char*. Up to here, everything works fine. No data loss or problems. But as soon as I pass filepath to any other function, my program starts doing crazy things. filepath is either turned into a bunch of \n characters or part of it's just missing. Here's the code:

#include <limits.h> //PATH_MAX
#include <unistd.h> //access()
#include <stdio.h>
#include <stdlib.h>

const char* _getfile(int argcount, const char ** argvars) {
    //Check if filepath has been given as console parameter
    if (argcount == 1) {
        exit(EXIT_FAILURE);
    }

    //Get absolute path of given filepath
    const char* relpath = argvars[1];
    char buffer[PATH_MAX + 1];
    const char* abspath = realpath(relpath, buffer);

    //Check if an absolute path could be found
    if (abspath) {
        printf("Source at '%s'.\n", abspath);
    } else {
        printf("No absolute filepath could be found for '%s'.\n", relpath);
        exit(EXIT_FAILURE);
    }

    //Check if file exists
    if(access(abspath, F_OK) != -1) {
        //Check file for read permissions
        if (access(abspath, R_OK) != -1) {
            return abspath;
        } else {
            printf("'%s' couldn't be accessed as it lacks read permissions.\n", abspath);
            exit(EXIT_FAILURE);
        }
    } else {
        printf("'%s' doesn't exist.\n", abspath);
        exit(EXIT_FAILURE);
    }
}

void _readfile(const char* filename) {
    //'filename' has now been changed!
    FILE* file = NULL;
    file = fopen(filename, "r");
    /*
    Read/print file contents etc.
    ...
    */

int main(int argc, const char** argv) {
    const char* filepath = _getfile(argc, argv);
    _readfile(filepath);
    return 0;

So say I pass "/Users/Token/Desktop/Test.txt" as a parameter in the console. When the absolute filepath is returned to main, namely still "/Users/Token/Desktop/Test.txt", everything's fine. When I pass it to _readfile(), inside of the function the filepath is now something like "\n\n\n\n\n\n..." or "/Users/To" and the rest of it is missing. It looks like a memory leak to me, but I can't find what I'm doing wrong. Also buffer seems to hold 1025 characters on my machine the last time I checked in the debugger, so that can't be the problem. I don't think this matters, but I'm using XCode on OS X El Capitan 10.11.13. Appreciating all help in advance!

Upvotes: 2

Views: 980

Answers (3)

4pie0
4pie0

Reputation: 29754

realpath resolves string passed to it and stores output in buffer passed as second argument

char buffer[PATH_MAX + 1];
const char* abspath = realpath(relpath, buffer);
//                                       ^^^
//                                in your case here

which is local variable in your code. As an array put on stack it becomes illegal to try to access it as soon as your function returns, and it happens before the caller even touches the something wished-to-be-returned-but-dissapeared.

Solution:

Pass the preallocated buffer for resulting string into _getfile:

const char *
_getfile(int argcount, const char ** argvars, char* buf)
{
    const char* relpath, *abspath;

    relpath = argvars[1];
    abspath = realpath(relpath, buffer);
    if (abspath != NULL)
    {
        // OK
        return abspath;
    } else {
        // handle
    }

Upvotes: 2

nsilent22
nsilent22

Reputation: 2863

You call realpath with a buffer which is locally allocated variable within your _getfile function. It gets destroyed when you return from your function and it is no longer valid. Thus you get weird values here. Use NULL as a second argument to the realpath call, so you'll get the pointer to the newly allocated buffer. After using it don't forget to free it.

Upvotes: 0

neerad29
neerad29

Reputation: 473

You are trying to return a local pointer. This will never work as when the function goes out of scope, all the local variables are destroyed. So the return value will have garbage as you are seeing.

You can do one of two things:

  1. Add an argument to the function which takes the return value.
  2. Define the return value in heap. (This is a bad approach, because in general, the calling code is responsible for allocating and deallocating heap memory. If you allocated the memory in this function, and deallocated it outside, its just bad programming :))

Upvotes: 1

Related Questions