考虑以下简单程序:
List<WebElement> rows = new List<WebElement>(table.FindElements(By.TagName("tr")));
var rowsCount = rows.Count;
for(int i=0; i<rowsCount; i++)
{
var row = rows[i];
// do what you need to do on this row e.g. row.Click();
row.Click();
// click back and wait
back.Click();
System.Threading.Thread.Sleep(10000);
rows = new List<WebElement>(table.FindElements(By.TagName("tr")));
}
使用GCC 8.2和#include <string>
#include <sparsehash/dense_hash_map>
int main()
{
google::dense_hash_map<std::string, int> map;
map["foo"] = 0;
}
(或-Wclass-memaccess
)进行编译会产生警告:
-Wall
问题是:
我在这里提出了一个问题:https://github.com/sparsehash/sparsehash/issues/149
答案 0 :(得分:2)
1。这是未定义的行为吗? 是。永远不要使用realloc()复制对象,因为有时它们具有指向资源的内部指针。当2个不同的对象运行其析构函数时,问题就会稍后出现。现在,相同资源发生了双重释放,一个完全没有。
2。您能否建议可以应用于应用程序代码的修补程序或解决方法(而不是通过更改Sparsehash或避免使用它)?
尝试
#include <memory>
并更改行
google::dense_hash_map<std::string, int> map;
到
google::dense_hash_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>, std::allocator> map;
现在,它不会使用Google的分配器libc_allocator_with_realloc
3。 (加分)您是否可以构建一个因此而实际上行为异常的程序(使用std :: string或您自己的非平凡类型)?到目前为止,尽管std :: string必须是非常常用的密钥类型,但我还没有看到使用std :: string作为密钥类型的代码中的任何问题。
不容易。因为您正在尝试引起不确定的行为。在您的测试程序中,我将输入至少32个字符的字符串,这样就不会启动小型字符串优化。并且可以在gcc的堆中进行测试,以查看其是否损坏。看到 1
答案 1 :(得分:1)
是的,这是未定义的行为。
但是请不要失望,只要std::string
不会在您的实现中存储任何内部指针,也不会在任何地方注册它们,无论如何它都会“起作用”。按位复制将等效于在目标位置进行移动构造并破坏源代码。
对于大多数(不是全部)字符串实现,无论是否是SSO,都是这种情况。
如果您使用的类型不能保证可轻易破坏性地移动,请使用其他分配器(最后一个模板参数)以避免按位移动。
由于按位复制的无效移动而导致程序崩溃很简单。
将此类型与google::dense_hash_map
一起使用:
class bang {
bang* p;
public:
bang() : p(this) {}
bang(bang const&) : bang() {}
bang& operator=(bang const&) { return *this; }
~bang() { if (p != this) std::abort(); }
};
答案 2 :(得分:0)
我想这段代码预期的是c ++ 20类属性可重定位。本质上,这是一个可以安全更改存储位置的对象。用c ++的话来说,这是一个对象,可以通过处理对象表示来安全地复制它,并且只要不再访问复制的对象,甚至不进行销毁,程序就可以保持预期的行为。
例如,C ++ 20标准可能未将此代码指定为“未定义行为”:
alignas(string) unsigned char buffer[sizeof(string)];
auto p = new(buffer) string{"test"};
alignas(string) unsigned char buffer2[sizeof(string)];
memcpy(buffer,buffer2,sizeof(string));//create a new string object copy of *p;
auto np = reinterpret_cast<string*>(buffer2);
(*np)[0]="r";
// the object at p shall not be accessed, not even destroyed.
如果类型具有引用其自身任何部分的非静态数据成员,则不应轻而易举地重定位该类型:
struct fail{
int a;
int b;
int* selected;
fail(bool is_a,int i){
if (is_a){ a=i; selected=&a;}
else { b=i; selected=&b;}
}
};
链表容器的某些实现也不能轻易重定位,例如,如果该容器包含一个作为根节点的成员。因此,dense_hash_map
不应仅与此类自记忆引用类型一起使用。