0

This is probably a noob question, but I don't even know what to google for.

I'm trying to implement a fuse filesystem and am having trouble passing structs, probably stemming from me being inexperienced with C++.

static int getStat(std::string path, struct stat *stout)
{
    ...
    struct stat *st = new struct stat();
    lstat(path.c_str(), st);
    // lstat correctly filled st according to gdb
    ...
    stout = st;
    // values are correctly copied to stout according to gdb
}

void something()
{
    struct stat *st = new struct stat(); // this might also be stack allocated by fuse, idk
    getStat("/", st);
    // but st is all zero now !?
}

What am I missing? How do I get my data out of the function correctly?

Cobra_Fast
  • 15,671
  • 8
  • 57
  • 102
  • Not sure if you omitted it or not but do note that `getStat` must return a value otherwise you have UB. – NathanOliver Aug 24 '17 at 15:36
  • And there's a potential memory leak as well, if you don't `delete` the structure before allocating and reassigning to `stout`. – Some programmer dude Aug 24 '17 at 15:37
  • Don't allocate stat on the heap (don't new)! Allocate on the stack and pass the address to lstat. –  Aug 24 '17 at 15:40
  • Another question: Do you *really* need to allocate the structure dynamically? *Twice?* – Some programmer dude Aug 24 '17 at 15:40
  • Also note that using `struct` when you declare a variable is a C-ism and is not needed in C++. – NathanOliver Aug 24 '17 at 15:40
  • As for the use-case, the normal way to use the `stat` function and its structure is to use a non-pointer variable and then use the address-of operator. As in `struct stat st; stat(path, &st);` And since you can assign a structure to another structure you don't need the argument to be a pointer either, just a reference. – Some programmer dude Aug 24 '17 at 15:44
  • @NathanOliver Might be needed here since the OP is using the `stat` *function*. Using `struct` for the structure removes any ambiguities. – Some programmer dude Aug 24 '17 at 15:45
  • @Someprogrammerdude Where are they using the `stat` function? All I see are value initialization calls to the `stat` type – NathanOliver Aug 24 '17 at 15:46
  • @NathanOliver Damn, the OP is using the `lstat` function. But doing that the OP still needs headers that declare both a `stat` structure *and* function, creating some ambiguities. Is the compiler required to be able to differentiate between type-names and functions in the global namespace when using a symbol in a declaration? I don't remember. – Some programmer dude Aug 24 '17 at 15:47
  • @Someprogrammerdude Aha. That would do it. Yes, if there is a stat type and a stat function then you need to decorate the type otherwise it is interpreted as the function. – NathanOliver Aug 24 '17 at 16:13

1 Answers1

3

You have to pass a double pointer to be able to reflect changed pointer in caller function.

So this is the solution

static int getStat(std::string path, struct stat **stout)
...
getStat("/", &st);

In , function arguments are always passed by value (except references). This means that in the function getStat(), stout is a copy of the pointer to struct that was passed in the function call.

So, when the new address is assigned to stout within the function, this has no effect on the original pointer to struct in something() (since stout within getStat() is only a copy of st within main()).

Since we are in you are able to use reference as @SomeProgrammerDude suggested.

static int getStat(std::string path, struct stat& stout)
struct stat st;
getStat("/", st);
kocica
  • 6,412
  • 2
  • 14
  • 35
  • 1
    Why use "double pointer" when programming in C++? C++ have pass-by-reference. – Some programmer dude Aug 24 '17 at 15:37
  • Its just explanation of problem. – kocica Aug 24 '17 at 15:38
  • Note that the question is tagged **C++** not C. In C++ you don't need to emulate pass-by-reference as you need in C, since C++ have native references. – Some programmer dude Aug 24 '17 at 15:39
  • I know and i mentioned that, but i just wanted him to understand why it doesnt work. – kocica Aug 24 '17 at 15:46
  • If I change the signature to double pointer the assignment `stout = st;` becomes invalid. My guess is I need to decorate that with additional special characters too, but which ones and where? – Cobra_Fast Aug 24 '17 at 15:47
  • Yes you have to do following `*stout = st;` (Add dereference to stout) – kocica Aug 24 '17 at 15:48
  • @Cobra_Fast Are you coming from Java, C# or JavaScript, before starting programming in C++? Because in C++ you don't need to use `new` to create objects. Perhaps you should [read a good beginners book or two](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)? – Some programmer dude Aug 24 '17 at 15:54
  • @Someprogrammerdude I'm coming from PHP and C# mainly. I've been on C adventures before, but nothing major. I would've done this project in C# if it was easily possible. My point of creating some of them with `new` is that I'm collecting them in a `map` and I might end up with quite a lot of them. – Cobra_Fast Aug 24 '17 at 15:57
  • 2
    @Cobra_Fast You don't need pointers to store objects in a map (or any other container). Begin with storing plain object instances instead. It usually doesn't matter if you have a large number of objects, there are ways of not having to copy large containers. And copying only a single object is usually quicker than you think. Not using pointers also means less chances of memory leaks, stray pointers, and actually *saves* some memory since you don't need space for the actual pointer (yes, the pointer needs space in memory as well, not only the object). – Some programmer dude Aug 24 '17 at 16:01
  • @Someprogrammerdude Okay thanks for the advice, I'll try how far I can get without `new`. – Cobra_Fast Aug 24 '17 at 16:04