ошибка double free или corruption при копировании объекта с помощью memcpy
у меня есть следующий код:
#include <iostream>
#include <string>
#include <cstring>
struct test {
std::string name;
size_t id;
};
int main() {
test t;
t.name = "147.8.179.239";
t.id = 10;
char a[sizeof(t)] = "";
std::memcpy(a, &t, sizeof(t));
test b;
std::memcpy(&b, a, sizeof(t));
std::cout << b.name << " " << b.id << std::endl;
}
когда я компилирую его и запускаю, он дает мне следующую ошибку:
147.8.179.239 10
*** Error in `./test': double free or corruption (fasttop): 0x0000000000bf9c20 ***
Aborted (core dumped)
оказывается, код может распечатать результат. Но как я могу исправить эту ошибку?
3 ответов
С помощью memcpy
то, как вы есть, у вас есть два std::string
объекты, которые точно идентичны. Это включает в себя любые указатели, которые они могут использовать внутри. Поэтому, когда деструктор для каждого объекта запускается, они оба пытаются освободить один и тот же указатель.
вот почему вам нужно использовать конструктор копирования или назначить один другому (т. е. использовать переопределенный operator=
). Он знает об этих различиях в реализации и обрабатывает их правильно, т. е. выделяет отдельный буфер памяти для целевого объекта.
если вы хотите извлечь строку, содержащуюся в std::string
нужно сериализовать объект известного представления. Тогда вы можете десериализовать его, чтобы преобразовать его обратно.
std::string s1 = "hello";
printf("len=%zu, str=%s\n",s1.size(),s1.c_str());
// serialize
char *c = new char[s1.size()+1];
strcpy(c, s1.c_str());
printf("c=%s\n",c);
// deserialize
std::string s2 = c;
printf("len=%zu, str=%s\n",s2.size(),s2.c_str());
выполните аналогичные действия для других объектов класса.
нельзя memcpy()
структура без стручка, как test
. Вы полностью разрушаете std::string
член.
вы должны используйте конструктор копирования для копирования объектов C++.
фактическая причина, по которой вы получаете двойную бесплатную ошибку, связана с тем, что вместо создания нового строкового объекта для ваших переменных a
и b
, вы просто копируете ссылку (a string
объект реализован с использованием переменной длины char *
).
С string
деструктор освобождает этот адрес памяти, когда ваша программа заканчивается, и, как объяснено выше, у вас есть два строковых объекта, указывающих на один и тот же адрес, вы получаете двойную бесплатную ошибку
этот будет работать, как сказал @JesperJuhl, вы должны использовать конструктор копирования
#include <iostream>
#include <string>
#include <cstring>
struct test
{
std::string name;
size_t id;
};
int main()
{
test t;
test a;
test b;
t.name = "147.8.179.239";
t.id = 10;
a=t;
b=t;
std::cout << b.name << " " << b.id << std::endl;
}