당신은 어떤 데이터 portLine
를 채우기되지 않습니다. 실제로 stream
에서 데이터를 읽지 않습니다.
너는 오용하고있다. eof()
. eofbit
플래그는 읽기 조작이 먼저 시도 될 때까지 갱신되지 않습니다. 그러므로 eof()
을 elavulating하기 전에 반드시 읽어야합니다.
portLine
및 name
버퍼를 유출하고 있습니다. 그리고 더 나쁜 것은 std::string
을 사용할 수 없으므로 Port::name
구성원이 char*
포인터라는 의미입니다. 즉, 여러 개의 Port
개체가 메모리의 동일한 실제 버퍼를 가리킬 가능성이 있습니다. Port
이 소멸자와 같이 나중에 해당 버퍼를 해제하려고하면 메모리 오류가 발생합니다. 난 강력하게 안전한 메모리 관리를 보장하기 위해 스마트 포인터를 STL을 사용하여 당신에게 제안 그러나
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
// better would be to use std::unique_ptr<char[]>, std::vector<char>,
// or std::string instead so the memory is freed automatically ...
char *portLine = new char[1000000];
int i = 0;
do
{
if (!stream.getline(portLine, 1000000))
{
delete[] portLine; // <-- free the buffer for line data...
throw std::system_error(Error::STREAM_ERROR);
}
if ((stream.gcount() == 0) || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine);
// better would be to use std::unique_ptr<char[]>, std::vector<char>,
// or std::string instead so the memory is freed automatically ...
char* name = new char[100];
while (iss.getline(name, 100, ';'))
{
if (iss.gcount() == 0) continue;
Port *port = new Port();
port->name = name; // <-- assumes ownership is transferred!
ports.addItem(port);
name = new char[100]; // <-- have to reallocate a new buffer each time!
}
delete[] name; // <-- free the last buffer not used...
passFirstRow = true;
} else {
++i;
}
}
while (!stream.eof());
delete[] portLine; // <-- free the buffer for line data...
return ports;
}
PortsContainer game::ParsePort(std::istream& stream, std::error_code& errorBuffer)
{
try
{
return ParsePort(stream);
}
catch (const std::system_error &exception)
{
errorBuffer = exception.code();
return PortsContainer(); // <-- don't forget to return something!
}
}
PortsContainer game::GetAvailablePorts()
{
std::ifstream stream("./ports.csv");
std::error_code errorBuffer;
return ParsePort(stream, errorBuffer); // <-- no need to check errorBuffer before returning!
}
:
대신 이와 비슷한 더 많은 것을 시도
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
// since you are using std::error_code, that means you are
// using C++11 or later, so use std::unique_ptr to ensure
// safe memory management...
std::unique_ptr<char[]> portLine(new char[1000000]);
int i = 0;
do
{
if (!stream.getline(portLine.get(), 1000000))
throw std::system_error(Error::STREAM_ERROR);
if ((stream.gcount() == 0) || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine.get());
// use std::unique_ptr here, too...
std::unique_ptr<char[]> name(new char[100]);
while (iss.getline(name.get(), 100, ';'))
{
if (iss.gcount() == 0) continue;
// use std::unique_ptr here, too...
std::unique_ptr<Port> port(new Port);
port->name = name.release(); // <-- assumes ownership is transferred!
// better to make Port::name use std::unique_ptr<char[]> and then std::move() ownership of name to it...
ports.addItem(port.get());
port.release();
name.reset(new char[100]); // <-- have to reallocate a new buffer each time!
}
passFirstRow = true;
} else {
++i;
}
}
while (!stream.eof());
return ports;
}
비록을 std::string
을 사용하면 될 것이다 최선의 선택 :
PortsContainer game::ParsePort(std::istream& stream)
{
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
PortsContainer ports;
bool passFirstRow = false;
std::string portLine;
int i = 0;
while (std::getline(stream, portLine))
{
if (portLine.empty() || (portLine[0] == '#'))
continue;
if (!passFirstRow)
{
std::istringstream iss(portLine);
std::string name;
while (std::getline(iss, name, ';'))
{
if (name.empty()) continue;
std::unique_ptr<Port> port(new Port);
port->name = name; // <-- make Port::name be std::string as well!
ports.addItem(port.get());
port.release();
}
passFirstRow = true;
} else {
++i;
}
}
if (!stream)
throw std::system_error(Error::STREAM_ERROR);
return ports;
}
먼저 iostream :: eof inside 루프 상태가 잘못된 것으로 간주됩니까?] (https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). 그렇다면 C++의'char' 문자열은 실제로는 *** null-terminate ** 바이트 문자열이라고 기억해야합니다. null-terminator (널 포인터와 혼동해서는 안 됨)는 중요합니다. 또한 할당 한 메모리는 초기화되지 않고 * 읽지 않아도 * 정의되지 않은 동작으로 연결된다는 것을 기억하십시오. 마지막으로 여기 저기에 메모리 누수가있을 수 있습니다. –
'sizeof name' 어떤 가치가 있습니까? –
std :: string_ YAIT (아직 또 다른 무능한 교사)를 사용할 자유는 아닙니다. –