const char * в моем классе имеет ненужные символы после того, как он вернулся из функции - PullRequest
1 голос
/ 02 декабря 2010

Класс:

class myclass {
  public:
    myclass(void);

    const char* server;

  private:
    char pidchar[6];
    int pidnum;

};

Функция

myclass parseINI(const char* file)
{
    myclass iniOptions;
    CSimpleIniA ini;
    ini.SetUnicode();
    ini.LoadFile(file);
    const char* server = ini.GetValue("", "server", "");
    iniOptions.server = server;
    std::cout << server << "\n"; // Prints the correct value here
    fflush(stdout);
    return iniOptions;


}

Вызов из основной функции

int _tmain(int argc, TCHAR* argv[])
{

 myclass options;
 options = parseINI("myapp.ini");
 std::cout << options.server << "\n"; // It prints junk here
 return 0;
}

Что я сделал не так?

Ответы [ 7 ]

5 голосов
/ 02 декабря 2010

const char*, возвращаемое GetValue(), вероятно, принадлежало объекту ini. Когда вы вышли из функции parseIni(), ini вышел из области видимости и был уничтожен, что может означать, что указатель больше не действителен.

Попробуйте использовать std::string для типа server вместо const char*.

2 голосов
/ 02 декабря 2010

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

const char* server = ini.GetValue("", "server", "");
iniOptions.server = server;

Скопируйте значение, которое возвращается в новый блок памяти, прежде чем вернуться из функции parseINI.

string server = ini.GetValue("", "server", "");
iniOptions.server = new char[server.length() + 1];
std::copy(server.begin(), server.end(), iniOptions.server);         
iniOptions.server[server.length()] = 0;
1 голос
/ 19 мая 2012

То, как вы используете класс как функцию, возвращает тип данных в C ++, совершенно неверно. В C ++ существует 2 типа данных: тип значения, ссылочный тип. класс принадлежит второму; Из функции вы можете вернуть данные типа значения или указатель на любые данные. Но вы не можете перенастроить объект ссылочного типа. Потому что объект ссылочного типа будет освобожден сразу после того, как код выйдет из области, в которой определен объект.

Вы можете сделать любым способом:

1: определить parseINI как:

     myclass* parseINI(const char* file) 
     {     
           myclass* iniOptions = new myclass();
           ........
           return iniOptions;   
      } 

, а затем используйте его так:

      myclass* options = parseINI("myapp.ini"); 

2: определить parseINI как:

       void parseINI(myclass& options, const char* file) 
        {     
           ........//asigne value to options's members
        } 

, а затем используйте его так:

        myclass options;
        parseINI(options,"myapp.ini"); 

3: Сделайте то, что вы сделали, но добавьте метод присвоения (operator =) в myclass

1 голос
/ 02 декабря 2010

Я предполагаю, что время жизни данных, на которые указывает char*, возвращаемых из CSimpleIniA::GetValue(), совпадает с самим объектом CSimpleIni.Таким образом, когда ini уничтожается, указатель, возвращенный из GetValue(), становится недействительным.(Я никогда не использовал CSimpleIni и не достаточно внимательно изучал документы, чтобы точно знать, но именно на это указывает поведение).

Я бы предложил изменить myclass::server на std:string объект и установить его, используя что-то вроде:

iniOptions.server = std::string(server);

, что даст объекту myclass::server собственную копию строковых данных.

1 голос
/ 02 декабря 2010
const char* server = ini.GetValue("", "server", "");

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

Использование std :: string или даже просто char [] будет предпочтительным, чтобы просто решить проблему с наименьшим количеством изменений, поскольку они будут назначены фактическим значением, а не местом в памяти, как указатели.

Что вы действительно должны сделать, так это посмотреть ссылочную прозрачность.Это предотвратит повторение подобных проблем

0 голосов
/ 02 декабря 2010

Проблема в том, что локальная переменная server указывает на символьный буфер, возвращаемый ini.GetValue(), который уничтожается при возврате paraseINI().

Один из способов исправить это - выделить новый буферсамостоятельно и скопируйте символы.

const char* server = ini.GetValue("", "server", "");
int length = strlen(server) + 1;  // length of the string +1 for the NULL character.
delete [] iniOptions.server; // free the old buffer
iniOptions.server = new char[length]; // allocate your own buffer
strncpy(iniOptions.server, server, length); // copy the characters

Чтобы это работало, вы должны сделать myclass::server неконстантным, и вы должны инициализировать его в NULL в конструкторе и удалить в деструкторе.

Лучший способ справиться с этой ситуацией - использовать std::string вместо char * для muclass::server.Таким образом, std::string позаботится об управлении памятью, а код будет безопасен для исключений.

Если вы сделаете muclass::server std::string, то просто сделаете

const char* server = ini.GetValue("", "server", "");
iniOptions.server = std::string(server);

И вам не нужно ничего с этим делать в конструкторе или деструкторе.

0 голосов
/ 02 декабря 2010

iniOptions располагается в стеке и удаляется автоматически, когда функция возвращается. Вы должны распределить его по куче, используя new()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...