Мусор при присваивании строк
Есть класс в котором содержится размер строки и указатель на строку buf, определена функция set, определен конструктор копии и перегружен оператор присваивания.
Coder::Coder(const Coder& ob)
{
m_buf = new char[ob.m_size];
m_size = ob.m_size;
strcpy(m_buf, ob.m_buf);
}
void Coder::set(const char* buf, int size)
{
m_buf = new char ('\0');
strcpy(m_buf, buf);
if (!size || size != strlen(buf) + 1) throw std::logic_error("logic error");
m_size = size;
};
Coder Coder::operator= (Coder& ob)
{
if (ob.m_size > m_size)
{
delete[] m_buf;
m_buf = new char[ob.m_size];
m_size = ob.m_size;
}
strcpy(m_buf, ob.m_buf);
return *this;
}
При выполнении следующих инструкций
Coder* pCoder = new Coder;
pCoder->set(buf_hello, strlen(buf_hello) + 1);
std::cout << "Coder pointer buf: "<<pCoder->buf() << std::endl;
Coder coder;
coder = *pCoder;
std::cout << "coder buf: " << coder.buf() << std::endl;
В pCoder записывается Hello Global World!, а в coder - Hello Global Wor + мусор. В чем проблема? Адреса разные, длина одинаковая.
Класс приведен ниже
class Coder
{
public:
void set(const char* buf, int size);
void set(int buf, int size);
char* buf() const { return m_buf; }
int size() const { return m_size; }
Coder() : m_buf(0), m_size(0) {};
Coder(const Coder& ob);
Coder operator= (Coder& ob);
private:
char* m_buf;
int m_size;
};
Ответы (2 шт):
Вобщем, так. Меняем только одно: ваш КОРРЕКТНО РАБОТАЮЩИЙ set (на утечку памяти плюнем).
void Coder::set(const char* buf, int size)
{
if (!size || size != strlen(buf) + 1) throw std::logic_error("logic error");
m_buf = new char[size];
strcpy(m_buf, buf);
m_size = size;
};
Скомпилируйте и проверьте - пропала ошибка В ДРУГОМ МЕСТЕ или нет?
Только учтите, что это все ваши проблемы не решает.
Вижу следующую цепочку событий:
1)
pCoder->set(buf_hello, strlen(buf_hello) + 1);
Тут метод Set() вызывает переполнение буфера и записывает часть вашей строки в область, за пределами блока памяти, выделенного оператором new().
2)
std::cout << "Coder pointer buf: "<<pCoder->buf() << std::endl;
Тем не менее соответствующая строка пока цела, по-этому её вывод отрабатывает корректно.
3)
Coder coder;
coder = *pCoder;
Перегруженный оператор присваивания перед тем, как скопировать строку, вызывает оператор new(), который выделяет новый блок памяти из свободной области, которая оказалась расположена следом за тем блоком, что был выделен предыдущим вызовом new(). А как мы помним, после предыдущего вызова new() у нас произошло переполнение буфера, и хвост строки оказался в свободной области. Новый оператор new() его и перезаписал, разместив в нём заголовок блока - вот вам и "мусорные символы".
Вывод: ошибка в методе set().