free():删除动态数组时在 tcache 2 中检测到双重释放
free(): double free detected in tcache 2 while deleting dynamic array
我正在尝试读取 .txt 文件并打印行,同时仅使用 c 风格的字符串。
int main(int argc, char * argv[]){
...
size_t size = 2;
char* line = new char[size];
char c;
while (file.get(c)) {
if(c != '\n'){
line[size - 2] = c;
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
size++;
} else{
line[size - 1] = '\n';
cout << line << endl;
delete [] line;
size = 2;
line = new char[size];
}
}
...
}
我收到错误 free(): double free detected in tcache 2
。有什么问题,如何解决?
I am getting the error free(): double free detected in tcache 2. What
is the problem and how can fix it?
通过理解这段代码的错误:
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
要记住的重要一点是 temp
和 line
是 指向字符数组的指针 ;也就是说,它们可以 refer 一个数组,但它们不(通过它们自己)代表数组的 copies。所以:
// sets (line) to a memory address where (size) bytes have been
// made available for you to use. Let's assume (line) gets set to
// 0x11223344
char* line = new char[size];
[...]
// sets (temp) to the memory address where (size+1) bytes have been
// made available for you to use. For the sake of the exmaple,
// let's assume (temp) gets set here to memory-address 0x12345678.
char* temp = new char[size + 1];
// Copies (size) bytes from (line) (aka starting at memory-address 0x11223344)
// to (temp) (aka starting at memory-address 0x12345678)
memcpy(temp, line, size * sizeof(char));
// tells the heap that you no longer need the byte-array starting at 0x11223344.
// After this delete[] returns, the heap is allowed to reuse those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] line;
// Sets the value of the (line) pointer to point to 0x12345678 instead.
line = temp;
// tells the heap that you no longer need the bytes starting at 0x12345678.
// After this delete[] returns, the heap is allowed to use those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] temp;
// Note that at this point, (line) is still pointing to 0x1234568, *but*
// you are no longer allowed to use the memory at that address!
// This is a problem, because on the next iteration of your while-loop,
// you are going to write to either line[size-2] or line[size-1]; either
// either way you are writing to freed memory, which will invoke
// undefined behavior and cause problems for you.
那么,如何解决这个问题?正如评论中所建议的那样,解决它的最佳方法是完全避免 new
和 delete[]
,而是坚持使用 std::string
,因为这样可以避免所有常见的悬挂问题指针、释放后使用、未初始化的内存读取、未终止的字符串等
如果您必须使用new
和delete[]
,但是(例如因为这是分配规则),那么您需要跟踪每个堆分配的生命周期;在这种情况下,这意味着意识到当您设置 line = temp;
时,这意味着 line
现在指向 相同的 数组 temp
指向,并且由于您的代码希望在将来使用该数组,因此您不应调用 delete[] temp;
因为它会删除 line
指向的堆分配,并将 line
保留为悬挂指针(即指向您不再被允许使用的内存)。
我正在尝试读取 .txt 文件并打印行,同时仅使用 c 风格的字符串。
int main(int argc, char * argv[]){
...
size_t size = 2;
char* line = new char[size];
char c;
while (file.get(c)) {
if(c != '\n'){
line[size - 2] = c;
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
size++;
} else{
line[size - 1] = '\n';
cout << line << endl;
delete [] line;
size = 2;
line = new char[size];
}
}
...
}
我收到错误 free(): double free detected in tcache 2
。有什么问题,如何解决?
I am getting the error free(): double free detected in tcache 2. What is the problem and how can fix it?
通过理解这段代码的错误:
char* temp = new char[size + 1];
memcpy(temp, line, size * sizeof(char));
delete[] line;
line = temp;
delete[] temp;
要记住的重要一点是 temp
和 line
是 指向字符数组的指针 ;也就是说,它们可以 refer 一个数组,但它们不(通过它们自己)代表数组的 copies。所以:
// sets (line) to a memory address where (size) bytes have been
// made available for you to use. Let's assume (line) gets set to
// 0x11223344
char* line = new char[size];
[...]
// sets (temp) to the memory address where (size+1) bytes have been
// made available for you to use. For the sake of the exmaple,
// let's assume (temp) gets set here to memory-address 0x12345678.
char* temp = new char[size + 1];
// Copies (size) bytes from (line) (aka starting at memory-address 0x11223344)
// to (temp) (aka starting at memory-address 0x12345678)
memcpy(temp, line, size * sizeof(char));
// tells the heap that you no longer need the byte-array starting at 0x11223344.
// After this delete[] returns, the heap is allowed to reuse those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] line;
// Sets the value of the (line) pointer to point to 0x12345678 instead.
line = temp;
// tells the heap that you no longer need the bytes starting at 0x12345678.
// After this delete[] returns, the heap is allowed to use those
// bytes for other (unrelated) things, so you are no longer allowed to
// read or write that memory region!
delete[] temp;
// Note that at this point, (line) is still pointing to 0x1234568, *but*
// you are no longer allowed to use the memory at that address!
// This is a problem, because on the next iteration of your while-loop,
// you are going to write to either line[size-2] or line[size-1]; either
// either way you are writing to freed memory, which will invoke
// undefined behavior and cause problems for you.
那么,如何解决这个问题?正如评论中所建议的那样,解决它的最佳方法是完全避免 new
和 delete[]
,而是坚持使用 std::string
,因为这样可以避免所有常见的悬挂问题指针、释放后使用、未初始化的内存读取、未终止的字符串等
如果您必须使用new
和delete[]
,但是(例如因为这是分配规则),那么您需要跟踪每个堆分配的生命周期;在这种情况下,这意味着意识到当您设置 line = temp;
时,这意味着 line
现在指向 相同的 数组 temp
指向,并且由于您的代码希望在将来使用该数组,因此您不应调用 delete[] temp;
因为它会删除 line
指向的堆分配,并将 line
保留为悬挂指针(即指向您不再被允许使用的内存)。