我正在尝试调整动态分配的字符串数组的大小;这是代码!
void resize_array() {
size_t newSize = hash_array_length + 100;
string* newArr = new string[newSize];
fill_n(hash_array,newSize,"0"); //fills arrays with zeros
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
hash_array_length = newSize;
delete [] hash_array;
hash_array = newArr;
}
不幸的是它不起作用并且给出了分段错误。任何想法为什么?这基本上是一个线性探测哈希表,其中元素在有0的地方插入,因此我使用fill_n用0填充新创建的数组。有什么帮助吗?
答案 0 :(得分:4)
memcpy( newArr, hash_array, hash_array_length * sizeof(string) );
这一行非常危险,std :: string不是普通的旧数据类型, 您无法确保memcpy可以正确初始化它,它可能会导致 未定义的行为,是c ++(或编程)最讨厌的行为之一。
此外,还有一个更好,更安全(在大多数情况下)的解决方案 c ++中的动态字符串数组,只需使用vector
//create a dynamic string array with newSize and initialize them with "0"
//in your case, I don't think you need to initialize it with "0"
std::vector<std::string> newArr(newSize, "0");
如果hash_array与newArr(std :: vector)的类型相同 复制的方式非常简单。
C ++ 98
std::copy(hash_array.begin(), hash_array.end(), newArr.begin());
C ++ 11
std::copy(std::begin(hash_array), std::end(hash_array), std::begin(newArr));
更好地将c ++视为一种新语言,它有太多不同于c的东西。 此外,还有很多像样的免费IDE,比如code :: blocks和QtCreator devc ++几乎已经死了。
如果您不熟悉c ++,那么c ++ primer 5是一本很好的书。
答案 1 :(得分:1)
如果string
实际上是std::string
(可能即使不是),那么这将会崩溃。您正在创建一个新的字符串数组,复制顶部的旧字符串类,然后释放旧字符串。但是如果字符串类包含分配内存的内部指针,这将导致双重释放,因为您所做的只是复制内部指针 - 而不是进行新的内存分配。
这样想;想象你有以下课程:
class foo
{
char* bar;
foo() { bar = malloc(100); }
~foo() { free(bar);
};
foo* ptr1 = new foo;
foo* ptr2 = new foo;
memcpy(ptr2, ptr1, sizeof(foo*));
delete ptr1;
此时,ptr2->bar
指向ptr1->bar
所执行的相同内存,但ptr1
及其保留的内存已被释放
最好的解决方案是使用std::vector
,因为它会自动处理调整大小,您根本无需担心复制数组。但是,如果您希望坚持使用当前的方法,则需要将memcpy
调用更改为以下内容:
for (int i = 0; i < hash_array_length; ++i)
{
newArr[i] = hash_array[i];
}
不仅仅是复制内存,而是调用类的复制构造函数并对其内容进行适当的复制。
答案 2 :(得分:0)
我怀疑罪魁祸首是memcpy
。 string
是复杂类型,它通过指针管理char数组(就像你现在正在做的那样)。通常使用赋值运算符完成复制字符串,对于字符串,它也复制自己的数组。但是memcpy只是复制指针的每字节字节,而delete []也删除了由字符串管理的数组。现在另一个字符串使用已删除的字符串数组,即BAAAD。
您可以使用std :: copy而不是memcpy,或者更好的是,使用std :: vector,这可以解决大多数动态内存处理问题。