Исключение С++: bad_alloc в ячейке памяти

Необработанное исключение по адресу 0x7650C41F в файле binary.exe: Исключение Microsoft C++: std::bad_alloc в ячейке памяти 0x003EEE00.

First-chance exception at 0x77983AB3 (ntdll.dll) in binary.exe: 0xC0000005: Access violation reading location 0x6F726369.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003DF0DC.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003DF0DC.
First-chance exception at 0x77983AB3 (ntdll.dll) in binary.exe: 0xC0000005: Access violation reading location 0x6F726369.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003DEA40.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003DEA40.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.
First-chance exception at 0x7650C41F in binary.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.
Unhandled exception at at 0x7650C41F in binary.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x003DEA40.
The program '[7632] binary.exe' has exited with code 0 (0x0).

Я не знаю, совершаю ли я ошибку новичка, но каждый раз, когда я пытаюсь запустить приведенный ниже код, я получаю ошибки, перечисленные выше - из того, что я могу собрать из различных сообщений на форуме и сообщений об ошибках, есть проблема с распределение памяти, но это все, что у меня есть.

Приведенный ниже код является укороченной версией моего проекта, так как исходные файлы довольно длинные и их не нужно публиковать.

int _tmain(int argc, _TCHAR* argv[])
{
    check(true);
    system("pause");
    return 0;
}

int check(bool initialCheck)
{
    char* path = getDocumentRootA(); strcat(path, "Test//file.test");
    char* filePathA = getDocumentRootA(); strcat(filePathA, "Test2\\file.test");
    char* filePathB = getDocumentRootA(); strcat(filePathB, "Test3\\file.test");
    cout << "Checking if files exists...";
    if (doesFileExist(path) == true)
    {
        cout << "Yes\n";
    } else if (doesFileExist(path) == false) {
        cout << "No\n"; // todo
    }
    cout << "Checking if other files exist...";
    if (doesFileExist(filePathA) == true && doesFileExist(filePathB) == true)
    {
        cout << "Yes\n";
    }
    return 0;
}
char* getDocumentRootA()
{
    CHAR documentRootC[MAX_PATH]; CA2W uDocumentRoot(documentRootC);
    HRESULT result = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, uDocumentRoot); CW2A documentRoot_T(uDocumentRoot); strcat(documentRoot_T, "\\");
    string documentRootTemp = documentRoot_T; char* documentRoot = const_cast<char*>(documentRootTemp.c_str());
    cout<<documentRoot;
    return documentRoot;
}

Вероятно, также стоит отметить, что я попытался изменить первую часть кода (см. пример ниже), чтобы функция getDocumentRootA() вызывалась только один раз, но это не решило проблему.

char* testvar = getDocumentRootA();
char* path = testvar; strcat(path, "Microsoft\\file.test");
char* filePathA = testvar; strcat(filePathA, "Windows\\AppLoc\\file.test");
char* filePathB = testvar; strcat(filePathB, "Windows\\U\\file.test");

person Ryan    schedule 28.03.2013    source источник
comment
Поскольку вы упомянули, что можете быть новичком, я хочу указать, что на самом деле у вас должно быть только одно выражение в строке. Иметь более одного оператора (все, за которым следует точка с запятой, очень плохо: код становится труднее читать, а отладка превращается в кошмар.   -  person Frecklefoot    schedule 28.03.2013


Ответы (1)


В getDocumentRootA() вы перенастраиваете указатель на переменную-член объекта, выделенного в стеке, что плохо, поскольку, как только вы покинете функцию, она будет очищена. Это еще хуже, поскольку вы не должны изменять внутренний член string, поэтому здесь есть две проблемы:

  string documentRootTemp = documentRoot_T; 
  ^^^^^^
  Object on the stack

  char* documentRoot = const_cast<char*>(documentRootTemp.c_str());
                       ^^^^^^
                       Pointer to said object


   return documentRoot;
          ^^^^^
          Returning said pointer

и вот где вы используете этот указатель:

  char* path = getDocumentRootA();
  strcat(path, "Test//file.test");
         ^^^^
         Modifying pointer to object that does not exist anymore

Вероятно, вам следует просто вернуть std::string из GetDocumentRootA(), а затем в check, используя c_str в тех местах, где вам нужно const char *. Вы можете использовать оператор +=, чтобы добавить char * к std::string, см. этот справочник. Вот очень простой пример, чтобы сделать мое предложение более конкретным:

#include <string>
#include <iostream>

std::string getDocumentRootA()
{
   std::string str( "Path//") ;

   return str ;
}

bool doesFileExist( const char *p )
{
   bool ret = false ;

   // Do checking here

   return ret  ;
}

int main()
{
   std::string str2( getDocumentRootA() ) ;

   str2 += "Test//file.test" ;

   std::cout << str2.c_str()  << std::endl ;

   if( doesFileExist( str2.c_str() ))
   {
      std::cout << "Yes" << std::endl ;
   }
   else
   {
      std::cout << "No" << std::endl ;
   }
}
person Shafik Yaghmour    schedule 28.03.2013
comment
Спасибо за ответ, я сделал, как было предложено, и изменил GetDocumentRootA(), чтобы вернуть строку, и изменил testvar на testvar.c_str, однако при компиляции я получаю следующую ошибку. Error 1 error C3867: 'std::basic_string<_Elem,_Traits,_Ax>::c_str': function call missing argument list; use '&std::basic_string<_Elem,_Traits,_Ax>::c_str' to create a pointer to member. Причина, по которой я не использовал testvar.c_str() (как я привык делать), заключается в том, что затем я получаю сообщение об ошибке IntelliSense, говорящее, что a value of type "const char*" cannot be used to initialise an entity type of "char *". - person Ryan; 28.03.2013
comment
@user1661022 user1661022 Добавлен пример, который, надеюсь, вам поможет. - person Shafik Yaghmour; 29.03.2013
comment
Спасибо, что нашли время, чтобы сделать это, ваш пример решил мою проблему - ваша помощь была очень признательна. - person Ryan; 29.03.2013