0

I have the following code written in C:

#include <windows.h>
#include <stdio.h>

WCHAR* test(){
    WCHAR var[256];

    int nSize = GetEnvironmentVariableW(L"SystemRoot", NULL, 0);
    GetEnvironmentVariableW(L"SystemRoot", &var, nSize);

    wprintf(L"%s\n", var);

    return var;
}

int main() {
    WCHAR* var = test();
    wprintf(L"%s\n", var);
    return 0;
}

When I compile it in Visual Studio and run it it works as expected. It prints result two times - in main func and in test. Output is:

C:\Windows
C:\Windows

But when I compile it on linux with mingw compiler via command

i686-w64-mingw32-gcc -o test.exe -O3 -Os -static -s test.c

it gives this output after starting:

C:\Windows
(null)

Why do the test() func return NULL when I'm using mingw and what to do to make it work properly? Thanks.

ph691
  • 1
  • 1
  • 4
    The array pointed to by `var`, being a local variable, doesn't exist after you left the function, so returning it doesn't make sense. You have undefined behavior here. It appearing to work on Windows is pure chance. – CherryDT Oct 07 '21 at 15:14
  • 2
    Does this answer your question? [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Retired Ninja Oct 07 '21 at 15:15
  • 3
    Did you read the warnings your compiler show you when you compile this code? – Jabberwocky Oct 07 '21 at 15:15
  • This may also be helpful: [How to access a local variable from a different function using pointers?](https://stackoverflow.com/questions/4570366/how-to-access-a-local-variable-from-a-different-function-using-pointers) – Retired Ninja Oct 07 '21 at 15:17
  • In addition to the above comments, you have a potential buffer overrun if that environment variable is more than 255 characters. You should either allocate the buffer based on the size that `GetEnvironmentVariableW(L"SystemRoot", NULL, 0)` returns, or don't call `GetEnvironmentVariableW(L"SystemRoot", NULL, 0)` and instead pass in the actual buffer size when you call `GetEnvironmentVariableW(L"SystemRoot", &var, /* actual buffer size here */)`. – jason44107 Oct 07 '21 at 15:18
  • You really should heed the compiler warnings. – David Heffernan Oct 07 '21 at 18:59

1 Answers1

3

You cannot return the address of a local variable, you get a compiler warning (which is actually more of an error).

You want this:

#include <windows.h>
#include <stdio.h>

WCHAR* test(WCHAR var[], int nSize) {
  GetEnvironmentVariableW(L"SystemRoot", var, nSize);
  wprintf(L"%s\n", var);
  return var;
}

int main() {
 // declare var outside the test function
  WCHAR var[256];

  // pass the address of var to test
  test(var, 256);

  wprintf(L"%s\n", var);
  return 0;
}

But be aware that 256 (like in var[256]) may not be enough. I leave it as an exercise to you to resolve this issue properly.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115