在这种情况下,为什么STD ::移动原因是Segfault?
为什么在这种情况下std :: move()
导致segfault?
#include <iostream>
struct Message {
std::string message;
};
Message * Message_Init(std::string message) {
Message * m = (Message*)calloc(1, sizeof(Message));
m->message = std::move(message);
return m;
}
int main() {
auto m = Message_Init("Hello");
return 0;
}
ps 请不要询问为什么消息
不以通常的C ++方式构建。
Why does std::move()
cause a SEGFAULT in this case?
#include <iostream>
struct Message {
std::string message;
};
Message * Message_Init(std::string message) {
Message * m = (Message*)calloc(1, sizeof(Message));
m->message = std::move(message);
return m;
}
int main() {
auto m = Message_Init("Hello");
return 0;
}
P.S. Please don't ask why Message
is not constructed in a usual C++ manner.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您真的想做这样的事情,则可以使用
安置新
。这使您可以在已经分配的一块内存中构造一个对象。一些标准容器使用
放置新
来管理其内部对象缓冲区。但是,它确实增加了与您所处物体的破坏者的并发症。在此处阅读以获取更多信息:有哪些用途用于“位置新”?
如@Selbie所建议的,我已经在
Message
的destructor上添加了一个明确的调用,也向free
呼叫以处理内存。我相信免费
的电话实际上应该指向最初由calloc
返回的缓冲区,因为可能会有差异(因此free(buf)
在这种情况下,但是在这里无法访问该指针)。例如,如果您为多个对象分配缓冲区,则在指向第二个对象的指针上调用
免费
是不正确的。If you really want to do something like this, then you can use
placement new
. This allows you to construct an object in a chunk of memory that is already allocated.Several of the standard containers use
placement new
to manage their internal buffers of objects.However, it does add complications with the destructors of the objects you place. Read here for more info: What uses are there for "placement new"?
As @selbie suggested, I have added an explicit call to the destructor of
Message
, and also a call tofree
to deallocate the memory. I believe that the call tofree
should actually have pointed to the buffer originally returned bycalloc
since there could be a difference (sofree(buf)
in this case, but that pointer is not accessible here).For example if you allocate a buffer for several objects, then calling
free
on the pointer to the second object would not be correct.关于C ++的分配的工作方式似乎存在误解。如果编译器遇到具有涉及类类型的评估操作,则它将寻找一个称为 copy/move分配运算符的特殊功能。然后调用此特殊功能执行复制/移动。一般而言,左手和右侧必须是初始化的对象才能正确工作。
在某些情况下,允许它使用非初始化的对象。在这种情况下,要复制/移动的对象的类具有一个琐碎的副本/移动式操作员。但是,大多数标准库类都不是微不足道的共配/可移动,尤其是
std :: String
不是。顺便说一句,您打电话给
std ::移动
并不重要。即使没有它,它也是不确定的行为。您必须在分配目标对象之前构造目标对象。您可以通过调用正常new
运算符或分配空间并使用放置新
new new new 在该空间中构造对象。There seems to be a misunderstanding about how assignment in C++ works. If the compiler encounters a assigment operation with class types involved, it looks for a special function called the copy/move assignment operator. This special function is then called to perform the copy/move. Generally speaking the left hand side and the right hand side have to be initialized objects for this to work correctly.
There is a special case in which it is allowed to use uninitialized objects. That is the case where the class of the objects that are to be copied/moved has a trivial copy/move assigment operator. However most of the standard library classes are not trivially copiable/moveable and in particular
std::string
is not.By the way it does not matter that you called
std::move
. Even without it, it would be undefined behaviour. You have to construct the target object before assigning to it. You can do that by either allocating and constructing the object in one shot by calling the normalnew
operator, or by allocating the space and use placementnew
to construct the object in that space.