C ++ : 읽기 데이터가 메모리에 영향을 줄 수있는 방법은 무엇입니까?
-
18-09-2019 - |
문제
나는 최근에 C ++에 더 깊이 들어가고 내 버그는 복잡해 보인다.
나는 물체의 벡터가 있고 각 물체에는 플로트 벡터가 포함되어 있습니다. 나는 모든 객체의 모든 플로트 값을 하나로 포함하는 추가 플랫 배열을 만들어야한다고 결정했습니다. 그것보다 조금 더 복잡하지만 문제의 요점은 플로트 값을 추출하는 객체를 통해 루프를 통해 객체의 벡터가 변경되거나 이상한 방식으로 손상된다는 것입니다. (내 읽기 작업은 모두 const 함수입니다)
또 다른 예는 MPI였습니다. 방금 시작하고 있었기 때문에 자체 메모리가 있고 데이터 전송이 발생하지 않고 매우 간단한 두 개의 다른 노드에서 정확히 동일한 코드를 실행하고 싶었습니다. 놀랍게도 세분화 오류가 발생했고 시간 추적 후 하나의 변수를 하나의 할당하면 완전히 다른 변수를 null로 설정하고 있음을 알았습니다.
따라서 궁금합니다. 읽기 작업이 내 데이터 구조에 영향을 줄 수있는 방법은 무엇입니까? 마찬가지로 겉보기에 관련이없는 운영이 다른 작업에 어떻게 영향을 미칠 수 있는지. 나는 그 간단한 설명에 대한 나의 문제에 대한 해결책을 기대할 수 없었지만 어떤 조언에 큰 감사를 표할 것입니다.
업데이트 : 여기에 코드의 세그먼트가 있습니다. 원래 전체 시스템을 이해하지 않고 얼마나 많은 것을 추출 할 수 있는지 확실하지 않기 때문에 원래 게시하지 않았습니다.
내가 방금 발견 한 한 가지는 평평한 배열에 값을 할당하지 않았고 대신 Cout을 대신했을 때 SEG 오류가 사라 졌다는 것입니다. 그래서 아마도 나는 배열을 잘못 선언하고 있지만, 내가 있었더라도 그것이 객체 벡터에 어떤 영향을 미칠지 확실하지 않습니다.
void xlMasterSlaveGpuEA::FillFlatGenes() {
int stringLength = pop->GetGenome(0).GetLength();
for (int i=0;i<pop->GetPopSize();i++)
for (int j=0;j<stringLength;j++)
flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);
}
float xlVectorGenome::GetFloatGene(unsigned int i) const {
return GetGene(i);
}
내 평평한 배열은 멤버 기능입니다
float * flatFitness;
SO처럼 생성자에 시작되었습니다.
flatFitness = new float(popSize);
Update 2:
위의 두 예제는 관련이 없으며 첫 번째 예는 멀티 스레드가 아닙니다. 두 번째 MPI 예제는 기술적으로이지만 MPI는 분산 메모리이며 고의적으로 생각할 수있는 가장 간단한 구현을 시도했습니다. 이는 코드를 독립적으로 실행하는 머신입니다. 그러나 추가 세부 사항이 하나 있습니다.
if node 1 then do bottom half of loop
if node 1 then do top half
다시 한 번 메모리를 격리해야합니다. 그들은 서로에 대해 아무것도 모르는 것처럼 작동해야합니다. 그러나이 조건부를 제거하고 두 루프를 모두 큐브로 만들고 오류를 제거합니다.
해결책
이것은 배열 생성자가 아닙니다.
float * flatFitness;
flatFitness = new float(popSize);
여기 힙에 플로트 하나를 만들고 값으로 초기화되었습니다. popSize
. 플로트 배열을 원한다면 괄호 대신 괄호를 사용해야합니다.
float *flatFitness = new float[popSize];
이것은 당신이 설명하는 문제를 쉽게 일으킬 수 있습니다. 또한 배열을 만들 때를 기억하면 사용을 삭제해야합니다. delete []
(결국):
delete [] flatFitness;
만 사용하는 경우 delete
, 그것은 작동 할 수 있지만 행동은 정의되지 않습니다.
배열 구문을 완전히 사용하지 않으려면 사용하지 않는 이유는 무엇입니까? std::vector
? 다음과 같은 팝 사이즈 요소의 벡터를 만들 수 있습니다.
#include <vector>
std::vector<float> flatFitness(popSize);
범위가 떨어지면 자동으로 해제되므로 걱정할 필요가 없습니다. new
또는 delete
.
업데이트 (Re : 댓글) : 이미 사용중인 경우 std::vectors
코드의 다른 곳에서는 살펴보십시오 std::vector::swap()
. 당신은 물건을 완전히 복사하지 않고 Cuda를 위해 버퍼링과 여기에서 수행하는 처리 사이에서 몇 개의 벡터를 앞뒤로 교환 할 수 있습니다.
다른 팁
나는 당신이 알지 못하는 멀티 스레딩 또는 메모리 부패 문제가 있다고 생각합니다. 당신이 설명하는 행동은 어떤 종류의 표준, 신분, 바람직한 행동이 아닙니다.
Jeffamaphone은 이것이 스레딩 문제라는 것이 옳을 수 있습니다. 또 다른 가능성은 당신이 읽고있는 객체가 이미 삭제되었을 것입니다. 그런 다음 유효하지 않은 주소에서 읽을 것입니다. 이 시점에 쓰고있는 데이터 구조는 이전에 벡터가 이전에 점유했던 동일한 위치에 저장 될 수도 있습니다. 이것은 당신이 묘사하는 행동을 초래할 것입니다.
편집하다 (업데이트에 따라) :
이것은 결함이있을 수 있습니다. stringLength
외부 루프 외부에서 초기화되지만 해당 외부 루프 중에 업데이트 해야하는 것처럼 보입니다.
int stringLength = pop->GetGenome(0).GetLength();
for (int i=0;i<pop->GetPopSize();i++)
for (int j=0;j<stringLength;j++)
flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);
제안 된 수정 :
for (int i=0;i<pop->GetPopSize();i++) {
int stringLength = pop->GetGenome(i).GetLength();
for (int j=0;j<stringLength;j++) {
flatGenes[(i*stringLength)+j]<< pop->GetGenome(i).GetFloatGene(j);
}
}