Почему функция не возвращает строку?

char* take_module_name()
{
    TCHAR FilePath[MAX_PATH + 1]; // буфер для имени файла
    GetModuleFileName(NULL, FilePath, sizeof(FilePath) / sizeof(FilePath[0]));

    int lastSlash = 0;
    for (int i = 0; i < MAX_PATH + 1; i++)
    {
        if (FilePath[i] == '\\' || FilePath[i] == '/')lastSlash = i;
    }

    
    char filename[40];
    strcpy(filename, &FilePath[lastSlash + 1]);
    filename[39] = '\0';

    return  filename;
}

Почему когда я вызываю эту функцию она не выводит имя файла, хотя filename в функции выводится нормально? Вызываю так:

cout << take_module_name();

Хотя если так делать то все работает, но через раз:

string file_way = (string)OBF("DEL /q %systemroot%\\Prefetch\\") + take_module_name();
cout << file_way;

P.s как оказалось цикл иногда возвращает неправильный lastSlash ,но почему ,для меня непонятно.


Ответы (3 шт):

Автор решения: Ildar
  1. изменяем string переданный по ссылке

     void foo(std::string& message)
     {
       message = "hello";
     }
    
  2. возвращаем string

     std::string foo()
     {
       std::string message = "hello";
       return message;
     }
    
  3. изменяем массив char переданный в функцию

     void foo(char* message)
     {
       strcpy_s(message, 6, "hello");
     }
    
  4. возвращаем указатель на динамический массив char выделенный в функции, но это очень плохой вариант, так как нужно чтобы кто-то снаружи зачистил память

     char* foo()
     {
       char* message = new char[6];
       strcpy_s(message, 6, "hello");
       return message;
     }
    

также рекомендую использовать функцию strcpy_s вместо strcpy так как c помощью неё вы будете уверены сколько символов вы записываете в целевую строку и избежите переполнения буфера если строка-источник длинней результирующей строки

→ Ссылка
Автор решения: KoVadim

О возврате указателя на локальную переменную уже написал @Ildar. Но в коде есть ещё одна ошибка - в следующем коде

for (int i = 0; i < MAX_PATH + 1; i++)
{
    if (FilePath[i] == '\\' || FilePath[i] == '/')lastSlash = i;
}

Дело в том, что строка FilePath может быть короткой, а в конце массива будет мусор. и там вполне могут быть символы слеша. Как исправить? Можно подсунуть правильную длину вместо MAX_PATH+1, но я так понимаю, это не интересно.

Можно так

for (int i = 0; i < MAX_PATH + 1; i++)
{
    if (FilePath[i] == '\\' || FilePath[i] == '/')lastSlash = i;
    if (FilePath[i] == 0) break; // достигли нулевого символа - выходим.
}

А можно просто занулить весь массив изначально.

→ Ссылка
Автор решения: AR Hovsepyan

К ответу KoVadim, хотел бы добавить, что у вас есть ошибка при передаче аргументов в функцию strcpy, вторым аргументом которого должен быть const char*, а вы передаете TCHAR*. Я бы предложил:

const std::string take_module_name()
{
    TCHAR FilePath[MAX_PATH + 1];  
    GetModuleFileName(NULL, FilePath, MAX_PATH);    
    int lastSlash = 0;       
    for (int i = 0; FilePath[i] != L'\0'; i++)
    {
        if (FilePath[i] == '\\' || FilePath[i] == '/')lastSlash = i;
    }
    return std::string( (char*)&FilePath[lastSlash + 1]);    
}
→ Ссылка