setevoy
setevoy

Reputation: 4662

getcwd() with pointer returns "null"

I'm trying to recall a bit about C programming.

And one task I found for myself - is to pass string's variable between functions with pointers.

So - what I want to do:

And here is my code:

#include <stdio.h>
#include <unistd.h>

int ch_str(char point1[]) {
    printf("Point 1: %s\n", point1);
}

int getpath (char point2[]) {
    printf("Path: %s\n", getcwd(point2, sizeof(point2)));
}

int main () {

    char str[20] = "this is string";
    char *pStr;
    pStr = &str;

    ch_str(pStr);

    char pathname[1024];
    char *pPathname;
    pPathname = &pathname;

    getpath(pPathname);

    printf("Direct: %s\n", getcwd(pathname, sizeof(pathname)));

    return 0;
}

ch_str() here - is just "test" for me, to be sure I'm doing right (he-he) with pointers. And - this part works.

But getcwd() with pointer as an argument - just retun "null":

$ ./deploy
Point 1: this is string
Path: (null)
Direct: /home/setevoy/ci

I suppose - here is some (big...) misunderstanding of the pointers in C from my side, but:

The getcwd() function copies an absolute pathname of the current working directory to the array pointed to by buf

Array (pathname[1024]) passed with the pointer pPathname, so - why getcwd() can't save path to pathname[1024] location? What I can't see here?

Upvotes: 1

Views: 2168

Answers (4)

Aif
Aif

Reputation: 11220

Quoting getcwd manpages:

RETURN VALUES

 Upon successful completion, a pointer to the pathname is returned.  Oth-
 erwise a NULL pointer is returned and the global variable errno is set to
 indicate the error.  In addition, getwd() copies the error message asso-
 ciated with errno into the memory referenced by buf.

So you can print errno (optionnaly, you can use strerror(3)) to get the reason the call failed.

Your code basically works on my computer, although my compiler complains a lot about your casts.

I don't get why you want to use this array, the manpage states that if you do not provide a buffer, it will be allocated, and you'll have to use free(3) on it. So basically, your code could just be:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

char* getpath (void) {
  char *path = getwd(NULL);
  printf("Path: %s\n", path);
  return path;
}

int main () {
  char * dir = getpath();
  printf("I've got current path: %s\n", dir);
  free (dir);

  return 0;
}

Upvotes: 1

tdao
tdao

Reputation: 17713

But getcwd() with pointer as an argument - just retun "null":

If you replace your original getpath with the following getpath2, you would see the expected behavior:

int getpath2 (char *point2) {
    printf("Path2: %s\n", getcwd(point2, 1024));
}

Now why does this work, and your original getpath doesn't?

First check the prototype of getcwd:

char *getcwd(char *buf, size_t size);

You see that it expects a pointer buf, not an array. You argue that, wait, isn't that an array parameter decays to pointer? That's right. But that the problem is your sizeof, which now is the sizeof a pointer, not an array, so it's (usually) 4.

But it still doesn't explain the null output? So carry on with the function description:

If the length of the absolute pathname of the current working directory, including the terminating null byte, exceeds size bytes, NULL is returned.

Here because 4 is not enough space, so you see null output.

Upvotes: 0

Aleksandar Makragić
Aleksandar Makragić

Reputation: 1997

When you pass array as argument, function will only get pointer to the first element. In this process information about array size is lost. So there is your problem.

getcwd(point2, sizeof(point2))); This sizeof() is problem.

Read more here: What is array decaying?

Upvotes: 2

kfx
kfx

Reputation: 8537

In C, arrays as function arguments are passed by-reference, not by-value.

It means that in your code, in function getpath the size of char point2[] is the size of char *, not the size of the array pointed by the argument.

Since the size of the pointer is too small to contain the whole path, NULL is returned instead. From getcwd manpage:

The getcwd() function copies an absolute pathname of the current working directory to the array pointed to by buf, which is of length size. If the length of the absolute pathname of the current working directory, including the terminating null byte, exceeds size bytes, NULL is returned, and errno is set to ERANGE; an application should check for this error, and allocate a larger buffer if necessary.

Upvotes: 2

Related Questions