Долго ищу в сети. Но бесполезно. Пожалуйста, помогите или попробуйте дать некоторые идеи:
Я обнаружил репродуктивную ошибку в шаблонном классе , когда я попытался выделить больше места для члена динамического массива, управляемого указатель с функцией друга . Если я перехожу к другой функции-члену или просто в Push (), чтобы завершить этот процесс, ошибка исчезла.
Независимо от частной / общедоступной доступности, ошибка покрывает все поля элемента массива accession , как только я попытался прочитать или удалить элемент в нем , ошибка произошла.
Компилятор GCC не дал четких советов. Ошибка не влияет на основные типы, такие как int.
Связывающий друг и Связывающий друг оба страдают от этой ошибки
Что-то не так в моем коде или есть какое-то ограничение, которое я не знал при использовании функции памяти?
Любое мнение, ссылка и ответ приветствуются.
PS: Чтобы сделать опубликованный код более четким, я упростил некоторый неважный код. Но чтобы предоставить достаточно информации , он все равно выглядит так долго , извините за
затруднение чтения.
PS2: можно сделать гарантию, что упрощенный код правильный.
Ошибка возникает в режиме Отладка (x64 и x86), Visual Studio 2017
и cmake 3.13.4- GCC 7.2.0 отладка цепочки инструментов с помощью gdb в VScode.
//Bizcard.hpp
class Bizcard
{
private:
char *name;
char *phone;
public:
Bizcard();
Bizcard(const char* n,const char* phone);//constructor
Bizcard(const Bizcard &b);//copy constructor
Bizcard& operator=(const Bizcard& b);//assignment operator
~Bizcard();
};
//Bizcard.cpp
#include"Bizcard.hpp"
#include<string.h>
#include<iostream>
Bizcard::Bizcard()
{
name = nullptr;
phone = nullptr;
}
Bizcard::Bizcard(const char* n ,const char* p)
{
//simplified...
}
Bizcard::Bizcard(const Bizcard &b)
{
//simplified...
}
Bizcard& Bizcard::operator=(const Bizcard& b)
{
if(this==&b)
return *this;
delete[] this->name;//Error would occur here if using
//friend func to expand array capacity
delete[] this->phone;
if(b.name==nullptr)
{
name = nullptr;
phone = nullptr;
return *this;
}
int nlen = strlen(b.name);
int plen = strlen(b.phone);
this->name = new char[nlen+1];
strcpy_s(name, nlen + 1, b.name);
this->phone = new char[plen+1];
strcpy_s(phone, plen + 1, b.phone);
return *this;
}
Bizcard::~Bizcard()
{
delete[] name;
delete[] phone;
}
//BagTemplate.hpp
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include"Bizcard.hpp"
template<typename Type>
void ChangeSize1D_binding(Type* array, int old_capacity, int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
Type* temp_array =new Type[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;//Point array to the dest of temp_array
}
template<typename T>
class Bag
{
public:
Bag(int bagCapability =3);
~Bag();
void Push(const T&);
void ChangeSize1D_self(int old_capacity, int new_capacity);
private:
T *array;
int capacity;
int top;
friend void ChangeSize1D_binding<T>(T* array, int old_capacity, int new_capacity);
template<typename Type>
friend void ChangeSize1D_unbind(Type* array, int old_capacity, int new_capacity);
};
template<typename T>
Bag<T>::Bag(int bagCapacity):capacity(bagCapacity)
{
if(capacity<1) throw "Capacity must be >0";
array = new T[capacity];
top = -1;
}
template<typename T>
Bag<T>::~Bag()
{
delete[] array;
}
template<typename T>
void Bag<T>::ChangeSize1D_self(int old_capacity,int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
T* temp_array =new T[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;
}
template<typename Type>
void ChangeSize1D_unbind(Type* array, int old_capacity, int new_capacity)
{
if(new_capacity<old_capacity)
throw "Paragram Error! New capacity must greater than the old one.";
Type* temp_array =new Type[new_capacity];
std::copy(array,array+old_capacity,temp_array);
delete[] array;
array = temp_array;
}
template<typename T>
void Bag<T>::Push(const T& x)
{
if(capacity ==top+1)
{
//this->ChangeSize1D_self(capacity,2*capacity);
ChangeSize1D_unbind(array,capacity, 2*capacity);
//ChangeSize1D_binding(array,capacity, 2*capacity);
/*T* temp_array = new T[2 * capacity];
std::copy(array,array+capacity,temp_array);
delete[] array;
array = temp_array;*/
capacity*=2;
}
array[++top]=x;
}
//main.cpp
int main()
{
Bag<int> IntBag;
IntBag.Push(1);
IntBag.Push(1);
IntBag.Push(1);
IntBag.Push(1);
Bag<Bizcard> BizcardBag;
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());
BizcardBag.Push(Bizcard());//Error may happen here since Push() it need
//expanding capacity(origin value: 3)
/*1.as predict, Push success if change size process is directly in Push()
2.when turn to ChangeSize1D(), same error occur
2.1 when change to private member func, no error
2.2 when change to public member func, no error
2.3 when change to private unbinding friend func, same error occur;means private or public doesnt effect behaviour
2.4 when change to private binding friend func, same error occur
*/
return EXIT_SUCCESS;
}
#CMakeLists.txt
cmake_minimum_required(VERSION 2.6)
project(BugReproduct)
include_directories("${PROJECT_SOURCE_DIR}/Bizcard")
add_subdirectory("${PROJECT_SOURCE_DIR}/Bizcard")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_executable(BugReproduct ArrayExpansion.cpp)
target_link_libraries(BugReproduct Bizcard)
#Bizcard/CMakeList.txt
add_library(Bizcard Bizcard.cpp)